Monday, April 14, 2014

What i have learned making angular-semantic-ui

Some times ago, i think two weeks ago i have started to developer angular.js directives for semantic UI modules. Full idea was to make SemanticUI - jquery free. So, today i'm finishing with the initial version of angular-semantic-ui project, and here is the list of my opinions about different tools which i used for this. First of all what i did. I made angular.js directives for the general SemanticUI modules, now is done following modules:
  • accordion
  • checkbox
  • dimmer
  • dropdown
  • modal
  • popup
  • raiting
  • sidebar
I'm planing to make also buttons, progressbars, animations and etc... But it will be in next versions. So what i have learned:
  • bower - A package manager for the web. Perfect tool, now no need to download angularjs, bootstrap and any another libraries by hand. Just wrote bower file, ala package.json and executed bower install and that's all. All dependencies are in bower_componentes directory.
  • grunt - The JavaScript Task Runner. Hard to share thinks about it, because i never used another task runners for javascript, but for first try it was good tool. Need to try also gulp, is anybody tried this? How do you like it? Grunt vs Gulp?
  • karma - test runner for javascript.
    On the AngularJS team, we rely on testing and we always seek better tools to make our life easier. That's why we created Karma - a test runner that fits all our needs.
  • How works ng-transclude directive
  • Angular.js directive - is the best way to access dom in your angular.js project
  • Angular.js directive - it is simple
There are also many another more technical things which i have learned in this project, will tell about it in next posts. If you're interesting in something about angular.js, semantic-ui, let me know in comments or in twitter and i will try to write post about it.

Sunday, January 12, 2014

Getting started: Weber + Mongodb

The main idea of this post is to show simple example how to build ElixirLang + Mongodb web application from scratch. First of all we must to get weber source code, build it and create new project. Get Weber with:
git clone git@github.com:0xAX/weber.git
build it with:
mix deps.get && mix compile
and create new project:
mix weber.new testMongoApp
Now go to the testMongoApp and build our new web application with:
mix deps.get && mix compile
Now we must install mongodb, here i will not tell how to do it. All instructions you can find at official mongodb web site. Let's think that you successfully compiled testMongoApp web application and have already launched mongodb. Open now your mix.exs file and add Mongoex to the deps:


Next step is to set up Mongoex at the lib/app.ex. Add there following lines to the start function:


We'll build simple web application, which will consists from 2 html pages and will be users saving and search by user name. Let's configure routing for our web application. It will be like this:


Here are 4 routes:
  • Render main page
  • Save user
  • Render search page
  • Search user age by name
So... Our web application uses mongodb database for user storing, let's create model for it in lib/model/users.ex


Here is User model with 2 fields: name and age. Now go to the Main controller. There are must be 2 actions there: index/2 and add/2. First action just renders lib/views/main/index.html template:


And second action gets user name and age from ajax request and save it to the database:


Second controller is for user search by name. It has two actions two: list and find, first action renders search page:


and second action handles user search:


As you can see at the templates source code we user jquery javascript library for DOM manipulation and sending AJAX request to the server. Here is client side code for it:


Links

Saturday, December 28, 2013

Weber - High Performance web framework for ElixirLang

Weber - is a open souce weber framework for Elixir programming language. It's very lightweight and easy to deploy. Main goal of Weber to help developers to develop scalable web applications in the usual rails-like style. Weber is in eary development stage now, first commit was 07.09.2013, but now it has many features like:
  • Project generation
  • Json parsing/generation
  • Websockets
  • Sessions
  • i18n [experimental]
  • Grunt.js integraion
  • HTML helpers
  • and many more
many features are in plans or in progress now like code reloading and etc...

Architecture


I started Weber as a hobby project and main point for was - to make high performace web framework. There are many optimizations in weber in different places, more details you can find in the previous post. Weber's workflow is easy. Web server gets request from user and pass it to the handler. Handler tried to parse and match request url and execute any action which dependes on request:



Routing


All weber's routing configuration is in route.ex file. There is: route marcros in Weber. Main goal of router is to connect URLs with controllers and actions. You no need to declare route macros in your project for configuring routing. It's already predefined after new project creation. Example of routing configuration:


You can see here that weber's router consist from route macros and on/4 clauses. Every on/4 gets four parameters which means what to response for certain url.
  • "GET" - HTTP method. Can be "GET","POST","PUT", "DELETE", "PATCH", "ANY"
  • "/" - url
  • :SimpleTodo.Main - controller
  • :add - action
So if weber gets "/" request, it will call :SimpleTodo.Main.add, will get response of it and will return user. Weber router supports different features: Regular expression in path:


Controller/Action declaration with '#':


Redirect:


Resource routing


Will generate:


Controllers


Main Unit in Weber is a controller. Every controller consists from action. Controller is a ussual Elixir module and Action is a ussual Elixir function with two parameters. For example:


Action parameters:
  • bindings - url bindings. If you have a route path: /add/:name, you will get here: [name: name]
  • connection - Plug record (connection info)
Every action must return one of predefined tuple. It can be:
  • {:render, [project: "simpleTodo"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Renders views from views/controller/action.html and sends it to response. Or without headers. {:render, [project: "simpleTodo"]}
  • {:render_inline, "foo <%= bar %>", [bar: "baz"]}} - Renders inline template.
  • {:render_other, Elixir.Views.Index, [foo: "foo"], []} - Renders any view in controller. Or without headers.
  • {:file, path, headers} - Sends file in response. Or without headers {:file, path}
  • {:json, [response: "ok"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Weber converts keyword to json and sends it to response. Or without headers: {:json, [response: "ok"]}
  • {:redirect, "/main"} - Redirects to other resource.
  • {:text, data, headers} - Sends plain text. Or without headers: {:text, data}
  • {:nothing, ["Cache-Control", "no-cache"]} - Sends empty response with status 200 and headers.
Every action can have own view. So if you have routing something like this:


And action:


Weber will render lib/views/main/index.html view.

Templates


Weber use EEx templates. It's like HAML in rails:


There are many HTML EEx helpers in the Weber:
  • Weber.Helper.Html - build html from Elixir
  • content_for - layout helper
  • include_view - include html part to the another html
  • Resource helper - script/css/audio/video...

Models


Weber has no opportunity to use/build data models, instead you can use Ecto library. Ecto is a domain specific language for writing queries and interacting with databases in Elixir. See examples.

Benchmark


As i said above i tried and trying now to make weber high perfomance. I found table of comparing json transfering, here is my table with the same test:

Platform Req/s 1000
NodeJS 27
Plain cowboy 32
ChicagoBoss 7.2
Zotonic 7.5
Weber 16.8


Conclusion


So... Weber is in eary development stage, but already has many features and good performance. It's easy to start to easy to develop. We're waiting your contribution. If you're Elixir guru or Elixir newbie we're waiting you in our irc channgel: #WeberMVC at freenode. If you will have any questions/suggestions or ideas for Weber, please let us know at irc channel or in issues.

Links


Saturday, December 7, 2013

Weber + Coffeescript

Today i started to work for GruntJS integration to the Weber framework. It was old issue #25 and now grunt integration is in master. In this post I will tell how to use CoffeeScript with Weber. First of let's create new weber project with grunt:
mix weber.new /home/user/NewProject --grunt
You will see standard weber project structure, but with 2 new files:
  • package.json
  • Gruntfile.js
Actually it's standard files.

package.json:


Gruntfile.js:


Let's add "grunt-contrib-coffee": "0.4.0" to the package.json, execute sudo npm install and update our Gruntfile.js:


Now create public/coffee/app.coffee and add some code:


Now just execute:
grunt coffee
And you will see /public/js/app.js with compiled coffeescript. Very simple! That's all.

If you will have any questions/suggestions/issues write us to the Weber's issues. We need contributors.

Monday, December 2, 2013

Weber-0.0.4 and some notes about optimization

I released Weber-0.0.4 at this week. And here are some words about it. Current release mainly is a bug fixing and optimization and you don't find any new major features in it. First of all about performance, it became much better than previous Weber-0.0.3. I tested Weber at my workstation, with approximately the same web applications with the different web frameworks, maybe these results are not very objective, but i can see that weber now comparable with other web frameworks in speed. I tested Weber with:
wrk -c2000 -t8 http://localhost:8080/
all web application were sesion disabled. And here are the results:

If we'll compare current results with the Weber-0.0.3, it showed really worse results, something about 1000Req/s, like ChicagoBoss. As i said, there were much work for optimization it. And here some words about optimization.

How i raised Weber performance


First of all macroses. Macro! Macro! Macro!, Yes, you can read in book by Dave's Thomas:
Macros can easily make your code harder to understand. So never use a macro when you could use a function.
And it's true. But... i was guided by the following principle:
If you can do something in compile time, do it.
Let's see in some examples. What is the standard Weber's workflow? User sends request to the some URL, for example to the /main. Weber need to parse this url, understand which resource to return to the user. So... Weber must to find view, read it's content, compile it with EEx if need and return to the user. But it's very labor-intensive occupation to find/read/compile view for the every user's request. Weber makes it simple. It reads and compile all views it in compile time and generates modules with function which will return alredy compiled view's content. Here is it:


That's all. Now if we have view which path is project/lib/views/layout/index.html, we'll get module: Elixir.Views.Layout.Index and if we'll call: Elixir.Views.Layout.Index.__view__, we will get compiled content of this view. And that's all! We read and compile all views only one time, in compile time, instead reading/compiling it for every request. Second little example. When the request comes, Weber must understand, which module to call for getting compiled view content. Previously i had a simple function which returned all views from the current project:


It's pretty simple and works perfectly. But fprof showed that it was the slowest part in Weber. I created macros which returns the same result:


It generates Elixir.Weber.Path module and number of functions. And weber does it in compile time too. Now we can call Elixir.Weber.Path.__root__ for getting root directory, or Elixir.Weber.Path.__views__ for getting all views of current project. That's All. There are many another little optimizations in weber, but here I described the main approaches. If you will have any questions/suggestions/problems with Weber, please write us to the issues. Any contributions are welcome!

Links


Saturday, October 26, 2013

Initial internationalization support in weber

Today i added initial internationalization support to the Weber and in this post i'll try to show how it works. For internationalization we have t helper from Weber.I18n module. Let's create new project with weber.new and configure route:

It will be simple web application with two endpoints: / - for the main page and /:lang for the changing language. We will have only one simple html template in the our application, it will be html page with two links En/De for english and german languages:

Here you can see 2 links and two t helper calls. Principe of works t t helper is very simple, it gets locale of current user and tries to find translation for given key. Now we must create language files in lang directory. Language file it is just json file with name like en_US or de_DE, it's structure can be like this:

And in the end of all, let's create controller with 2 actions, first action will be for main page rendering and second action will be for language changing:

First action - action - is very simple and it just render main page with 2 links. Second action - change_locale - gets language from URL, updates locale for current user and updates the main page. That's all very simple. Internationalization support in very early stage in Weber, if you find a bugs or you will have questions/suggestions, please write us to the issues

Sunday, October 20, 2013

Weber-0.0.2 features

I'm continue to develop Weber, who don't know what is it Weber, can knows from previous posts that Weber is a Rails-like web framework written with Elixir programming language. Some times ago i released Weber with version - 0.0.2 and now it has many new features. Let's see what we have now.

Controllers


Weber controllers now have many different response types:
  • {:render, [project: "simpleTodo"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Render views with the same name as controller and sends it to response.
  • {:render_inline, "foo <%= bar %>", [bar: "baz"]}, []} - Render inline template.
  • {:file, path, headers} - Send file in response.
  • {:json, [response: "ok"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Weber convert keyword to json and sends it to response.
  • {:redirect, "/main"} - Redirect to other resource.
  • {:text, data, headers} - Sends plain text.
  • {:nothing, ["Cache-Control", "no-cache"]} - Sends empty response with status 200 and headers.
Also Weber now has API for getting request parameters, you can get body, method, cookie and other request parameters with the Weber.Http.Params API, it's very easy to use:


Routing


There are some new features in routing too... First of all you can declare route as Controller#action, for example:


Now you can pass any parameters to the URL query string and get it's values with the Weber.Http.Params.param/1 function. For example you got request for: /user?name=0xAX, you can get name parameter's value like this:


Helpers


Html Helper


Html helpers gives you opportunity to generate html templates from elixir:

Include view helper


Include view helper helps to include other views inside another.


Resource Helpers


You can include your static resources like javascript, css, favicon or image files with resource helpers:


Session API


If you will get Weber from master branch, there is sessions support there and simple API for managing sessions:
  • get_session() -> [] | [{atom, binary()}]
  • get_session(key :: atom()) -> [] | binary()
  • set_session_val(key :: atom(), val :: binary()) -> :ok

Logo


And the latest good news in this post, we have a logo:

thank you @caiotarifa for this great work.

Conclusion


Yes, Weber now has many new features as Sessions API, Helpers, Json encoding/decoding and etc... We waiting new contributors, you can help Weber to grow via submiting pull request (If you're interesting - Weber Roadmap, help us with translation onto your language (I18n In development), or just set up star at github. . If you will have any questsions/bug reports/suggestions write us to the issues or join to the #WeberMVC at irc.freenode.net.

Saturday, September 21, 2013

Writing simple chat application with Weber and Elixir

–°ontinue to develop Weber, and now it has more features than Weber-0.0.1, like:
  • https support
  • redirect support
  • http headers in response
  • we will have an own logo soon...
And of course main feature for this moment is WebSocket support, which i added yesterday. Time to look at some examples. As i said we have WebSocket support now in Weber, let's write simple web chat application.

New project


First of all we must to create new Weber project. Get Weber from github:
git clone https://github.com/0xAX/weber.git
Go to the Weber's root directory and create new project with:
mix weber.new /home/user/SimpleChat
Weber creates project directory with initial project template for our chat. Go to the /home/user/SimpleChat directory and execute following commands for getting dependencies and compiling chat application:
mix deps.get && mix compile
You can run empty weber project after successful compilation with executing:
./start.sh
and open it with browser at http://localhost:8080 Now we can start to develop our chat application.

Routing


First of all we must to declare routing for our chat application. It will be three route path:
  • / - for login page;
  • /join/:username - join to the chat room;
  • /chat/:username - render chat room page.
like this:


Views and Controllers


We will have 2 views for chat application:
  • login.html - simple template for login
  • chat.html - main chat's view
login.html:

Here is the simple html template with one input and button elements. I'm using Bootstrap and AngularJS for building my frontend code, but you can use any frontend libraries which you likes for building your applications. As i said here is very simple html template with one input and one button. Button has ng-click event handler. When user presses on login button, sends AJAX post requests to the controller with user's username:

Unfortunatelly now we have now sessions support in Weber, it will be in next versions, so here is very primitive authorization, we save it in gen_server process state. After successful login we redirect to the chat.html page. Chat's template is:

Here is the simple chat template with textarea element, and panel with input and button for sending chat message. We control it with SimpleChatRootController in frontend:

Here we can see that after controller's initialization, it opens WebSocket connection with 3 callbacks:
  • websocket.onopen
  • websocket.onmessage
  • websocket.onclose
We do nothing when WebSocket's connection is open. If connection close we redirect to the /. If we receive message we parse message body and message author and add it to the chat area. Let's see how to handle websocket connection at the backend part. Every Weber's websocket controller must have 3 callbacks:
  • websocket_init - new websocket connection
  • websocket_terminate - websocket connection is terminate
  • websocket_message - handles incoming messages.
Websocket conrtoller for our chat:

Here you can see 3 calbacks which i described above. Every callback takes pid parameter, which is pid of current websocket connection, and websocket_message takes pid and message. And 3 :gen_server.cast calls to the our mock gen_server, for adding new user, removing new user and sending message to the all users. Here is the implementation of this gen_server:

That's all. Now you can compile chat application with mix compile and launch it with ./start.sh. Full source code of chat example you can find - SimpleChat. Weber now is only at the start of developing and we have many plans: adding session API, html generators, helpers and many many more. If you will have any questions, suggestions or you want to take part in Weber developing write us to the Weber issues at Github.

Links


Monday, September 16, 2013

Elixir at practice

As you can know from my previous blog posts (Using elixir to write ybot plugins, Example of usage elixir with and Started to dive into elixir-lang) some times ago i started to learn and use Elixir language. I'm using elixir not very much time, but already have some feels about it. Practical part of usage of elixir is - Weber. It is a MVC web framework for Elixir, and yesterday i released Weber-0.0.1: In this post i will try to describe my feels about Elixir.

Mix


First of all about mix tool. Mix is a first Elixir's tool with which we meet in practice when started to use the elixir.
Mix is a build tool that provides tasks for creating, compiling, testing (and soon deploying) Elixir projects. Mix is inspired by the Leiningen build tool for Clojure and was written by one of its contributors.
We can create new Elixir project with: mix new project_name Build it with: mix compile Handle dependencies: mix deps.get && mix deps.compile And the main mix's feature as i think is a support of custum tasks. Mix task is just a Elixir module with mixed Mix.Task and run function. For example i'm using custom mix task in Weber for creating new project template:

OTP


As Elixir is built on top of Erlang virtual machine, we can easily to build OTP application with Elixir. Root supervisor: And simple gen_server: compile and start it with: iex -S mix

Testing


There is ExUnit! It is a unit test framework that ships with Elixir. Let see in routing functions from the Weber: And now we can write unit tests for it with ExUnit:

Libraries


Although Elixir is now young language, it has good set of libraries: and etc... Or you of course can use any erlang libraries. Just include it to your mix.exs file as: and execute mix deps.get

Links


In the end of this post i want to say many thanks to the Elixir community which helped me all this day, you're great!

Wednesday, September 4, 2013

[GIT] Sync local fork with main repository

I very often use Github/Git for my and not only my projects and this post is something like memo for myself, but i think it can be useful for somebody else. SHow to sync your fork with main repository: First of all set new remote repo:
git remote add upstream https://github.com/user/repo.git
Now fetching last changes:
git fetch upstream
And now as we fetched the upstream repository, we must to merge its changes into our local branch.
git merge upstream/master
@0xAX