weber 0.1.0

weber - is Elixir MVC web framework.

Homepage: http://0xax.github.io/weber/index.html

Platform: Hex

Language: Elixir

License: MIT

Repository: https://github.com/elixir-web/weber

View on registry: https://hex.pm/packages/weber/

Documentation: http://hexdocs.pm/weber/0.1.0


Weber

Weber - is a MVC Web framework for Elixir.

Build Status

Join the Community

#WeberMVC on freenode IRC

Mail listing

Build Status

Features

  • MVC web framework;
  • Project generation;
  • Json generation with exjson;
  • Websocket support;
  • HTML helpers;
  • Web controller Helpers.
  • i18n support;
  • Live code/templates update
  • Sessions support;
  • weber-contrib

Quick start

  1. Get and install Elixir from master.
  2. Clone this repository.
  3. Execute make && make test in the weber directory.
  4. Create new project with: mix weber.new /home/user/testWebApp.

Now go to the /home/user/testWebApp and execute there: mix deps.get && mix compile --all --force. Then you can try to run your testWeberApplication with:

./start.sh

or run it in daemon mode:

./start.sh --no-shell

and go to the http://localhost:8080/

For more details see in examples directory and Weber's API.

Directory structure

Dir/File Description
./start.sh Startup script
./lib/controllers Directory with web controllers
./lib/helpers Helper functions
./lib/models Directory for models (ecto)
./lib/views Directory with EEx views
./lib/app.ex Application startup settings
./lib/config.ex Configuration file.
./lib/route.ex File with routes declaration
./public Directory for static files (css, js ....)

Routing

Routing declaration is in route.ex files:

 route on("GET", "/", :Simpletodo.Main, :action)
 |> on("POST", "/add/:note", :Simpletodo.Main, :add)
 |> redirect("GET", "/redirect", "/weber")
 |> on("ANY", %r{/hello/([\w]+)}, :Simpletodo.Main, :action)

Also on supports following syntax:

 route on("GET", "/", "Simpletodo.Main#action")
 |> on("POST", "/add/:note", "Simpletodo.Main#add")

It is route macro which value is chain of on functions with 3 parametes:

  • Http method
  • Route path, can be binding (starts with ':' symbol);
  • Module name of controller;
  • Function name from this controller.

Http method can be:

  • "GET"
  • "POST"
  • "PUT"
  • "DELETE"
  • "PATCH"
  • "ANY"

You can set up resource in routing:

 route resources(:Controller.Photos)

It will be the same as

route on("GET", "/controller/photos", :Controller.Photos, :index)
 |> on("GET", "/controller/photos/new", :Controller.Photos, :new)
 |> on("POST", "/controller/photos", :Controller.Photos, :create)
 |> on("GET", "/controller/photos/:id, :Controller.Photos, :show)
 |> on("GET", "/controller/photos/:id/edit, :Controller.Photos, :edit)
 |> on("PUT", "/controller/photos/:id, :Controller.Photos, :update)
 |> on("DELETE", "/controller/photos/:id, :Controller.Photos, :destroy)

Build url from code

You can build url from your elixir code with:

import Weber.Route
route on("GET", "/", "Simpletodo.Main#action")
 |> on("POST", "/add/:note", "Simpletodo.Main#add")
# generates: /add/1
link(:Elixir.Simpletodo.Main, :add, [note: 1])

Controllers

Every Weber's controller is just an elixir module, like:

defmodule Simpletodo.Main do
 import Simplemodel
 use Weber.Controller
 layout false
 def action(_, conn) do
 {:render, [project: "simpleTodo"], []}
 end
 def add([body: body], conn) do
 new(body)
 {:json, [response: "ok"], [{"Content-Type", "application/json"}]}
 end
end

Every controller's action passes 2 parameters:

Controller can return:

  • {:render, [project: "simpleTodo"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Renders views from views/controller/action.html and sends it to response;
  • {:render, [project: "simpleTodo"]} - the same without headers;
  • {:render_inline, "foo <%= bar %>", [bar: "baz"]}} - Renders inline template;
  • {:file, path, headers} - Sends file in response;
  • {:file, path} - the same without headers;
  • {:json, [response: "ok"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Weber converts keyword to json and sends it to response;
  • {:json, 200, [response: "ok"], [{"HttpHeaderName", "HttpHeaderValheaderVal"}]} - Allows a custom status;
  • {:json, [response: "ok"]} - the same without headers;
  • {:redirect, "/main"} - Redirects to other resource;
  • {:text, status, data, headers} - Sends plain text;
  • {:text, data, headers} - the same without status;
  • {:text, data} - the same without headers;
  • {:nothing, ["Cache-Control", "no-cache"]} - Sends empty response with status 200 and headers;
  • {:nothing, ["Cache-Control", "no-cache"], http_status :: integer} - Sends empty response with custom status.

Controllers can also raise at any point in the action and immediately render a response:

defmodule Simpletodo.Main do
 import Simplemodel
 # Add :unauthorized to list of known responses
 render_when_raise :unauthorized, {:text, 401, "Action prohibited.", []}
 def action([user_id: user_id], conn) do
 if unauthorized_user_id?(user_id) do
 # Immediately render the known response
 raise_and_render :unauthorized
 end
 {:render, [project: "simpleTodo"], []}
 end
end
  • render_when_raise(value, response) - macro that adds to the known responses to render if specific value is raised
  • raise_and_render(value) - raises a WeberControllerException and renders a response based on the known responses

Request params

Sometimes it is necessary for the request parameters in the controller. For this point can be used Weber.Http.Params API.

defmodule Simplechat.Main.Login do
 import Weber.Http.Params
 use Weber.Controller
 layout false
 def render_login([], conn) do
 # get body request
 body = get_body(conn)
 #
 # Do something with param
 #
 {:render, [project: "SimpleChat"]}
 end
end

If you need to get parameters from query string, it is easy to do with param/1 API. For example you got request for: /user?name=0xAX, you can get name parameter's value with:

defmodule Simplechat.Main.Login do
 import Weber.Http.Params
 use Weber.Controller
 def render_login([], conn) do
 name = param(:name, conn)
 #
 # Do something with param
 #
 {:render, [project: "SimpleChat", name: name]}
 end
end

You can find the full API at the wiki.

Before/After request hooks

You can define __before__ or after __after__ hooks in your controller. It will pass two parameters:

  • :action - action name
  • conn - connection parameter
defmodule Simplechat.Main.Login do
 def render_login([], conn) do
 {:render, [project: "SimpleChat", name: "WeberChat"]}
 end
 #
 # Executes before request
 #
 def __before__(:render_login, conn) do
 conn
 end
 #
 # Execute after response
 #
 def __after__(:render_login, conn) do
 conn
 end
end

Helper

Html Helper

Html helpers helps to generate html templates from elixir:

defmodule Simpletodo.Helper.MyHelper
 import Weber.Helper.Html
 # Generates <p>test</p>
 def do_something do
 tag(:p, "test")
 end
 # Generates <p class="class_test">test</p>
 def do_something do
 tag(:p, "test", [class: "class_test"])
 end
 # Generates <img src="path/to/file">
 def do_something do
 tag(:img, [src: "path/to/file"])
 end
end

Tags with blocks

defmodule Simpletodo.Helper.MyHelper
 import Weber.Helper.Html
 # Generates <div id="test"><p>test</p></div>
 def do_something do
 tag(:div, [id: "test"]) do
 tag(:p, "test")
 end
 end
end

Partials

Include html partials to the your template with:

<%= render "Partial", [test: "Hello"] %>

You must have "your_project_name/lib/views/partials/Partial.html" with:

<%= @test %>

Resource Helpers

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

#
# Generates: <script type="text/javascript" src="/static/test.js"></script>
script("/static/test.js")
# If no value is passed for src it defaults to "/public/js/application.js"
script()
#
# Generates: <link href="/static/test.css" rel="stylesheet" media="screen">
#
style("/static/test.css")
# If no value is passed for href it defaults to "/public/css/application.css"
style()
#
# Generates: <link href="/public/img/favicon.ico" rel="shortcut icon" type="image/png">
favicon("/public/img/favicon.ico")
# If no value is passed for href it defaults to "/public/img/favicon.ico"
favicon()
#
# Generates: <img src="/public/img/example.jpg" alt="Image" class="some-class" height="100" width="100">"
image("/public/img/example.jpg", [alt: "Image", class: "some-class", height: 100, width: 100])
#
# Generates: <audio src="/public/audio/sound">
audio("/public/audio/sound")
#
# Generates <link href="my.rss" type="application/atom+xml" title="My feed">
atom("my.atom", "My feed")
#
# Generates <link href="my.rss" type="application/rss+xml" title="My feed">
rss("my.rss", "My feed")
#
# Generates:
# <audio autoplay="autoplay">
# <souce src="/public/audio/sound1"></souce>
# <souce src="/public/audio/sound2"></souce>
# </audio>
#
audio(["/public/audio/sound1", "/public/audio/sound2"], [autoplay: true])
#
# Generates: <video src="public/videos/trailer">
video("public/videos/trailer")
#
# Generates:
# <video height="48" width="48">
# <souce src="/public/videos/video1"></souce>
# <souce src="/public/videos/video2"></souce>
# </video>
video(["/public/videos/video1", "/public/videos/video2"], [height: 48, width: 48])

Controller Helpers

content_for_layout and layout

NOTE: Now all views and layout files must start with capital letter.

All controllers got main.html by default for views, but you'd might change it.

You can create custom layout for you controller:

Create Layout.html in the lib/views/layouts directory and put there:

<!DOCTYPE html>
<html>
 <head>
 <title>
 My Project
 </title>
 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
 </head>
 <body>
 <div id="container">
 <%= @content_for_layout %>
 </div>
 </body>
</html>

Than declare layout helper in your controller:

defmodule TestController.Main do
 use Weber.Controller
 layout "Layout.html"
 #
 # Here are some actions
 #
end

And you have lib/views/Main.html with:

Hello World!

Weber puts lib/views/Main.html content inside <%= content_for_layout %> and renders it in the response.

Logging

Weber uses exlager for the logging. For using it just set up:

log: true

in your config and use it:

defmodule LogTest.Main do
 require Lager
 def action([], _conn) do
 Lager.info "New request"
 {:render, []}
 end
end

Internationalization

Important Experemental now

See - Weber Internationalization

{
 "HELLO_STR" : "Hello, It is weber framework!",
 "FRAMEWORK_DESCRIPTION" : "Weber - is a MVC Web framework for Elixir."
}

and you can use it like:

<span><%= t(@conn, "HELLO_STR") %></span>

in your html template.

Websocket

You can handle websocket connection and incoming/outcoming websocket message in your controllers.

First of all you need to designate websocket controller in your config.ex file in webserver: section, like:

ws:
 [
 ws_mod: :Handler
 ]

After it you must implement 3 callbacks in your controller like this:

defmodule Simplechat.Main.Chat do
 def websocket_init(pid, conn) do
 #
 # new websocket connection init
 #
 end
 def websocket_message(pid, message, conn) do
 #
 # handle incoming message here
 #
 end
 def websocket_terminate(pid, conn) do
 #
 # connection terminated
 #
 end
end

All websocket connections are must start with prefix /_ws/.

Session

Session API

Testing requests

Currently, one way to test requests is using exunit and the hackney http client as we do in our own tests.

This is not as convenient and expressive as more established frameworks like rspec for rails offer but we are planning to improve this in the future.

Mix tasks

Create new project

mix weber.new /home/user/projectName

Version

mix weber --version

Help

mix weber --help

Print all current routes

mix weber.routes

Dependencies

Contributing

See Contributing.md

Additional info

Author

@0xAX.

веселые картинки развлекательные гифки интресные факты смешные видео смешные истории из соцсетей

GitHub Repository

elixir-web/weber elixir-web/weber

[WiP] Web framework for Elixir inspired by Rails [#WeberMVC at freenode]

http://elixir-web.github.io/weber/

Language: Elixir

Created: September 07, 2013 19:02

Last updated: March 09, 2015 21:19

Last pushed: August 11, 2014 05:34

Size: 3.83 MB

Stars: 324

Forks: 40

Watchers: 34

Open issues: 10

Top Contributors

Matheus Cáceres Nikita K. Christian Di Lorenzo Adam Kittelson Paulo A Pereira Leo Correa Dickson S. Guedes Josh Adams Caio Tarifa Darko Fabijan Kofi Boakye Michael Simpson tmaeda Sven Riedel Toby Hede Paul DiPietro Amol Hatwar David Rueck Dmitry Aleksandrov(Russ) Glen Holcomb

Releases

  • 0.1.0 - May 02, 2014 18:28

Related Projects

anaphora 0.1.1
The anaphoric macro collection for Elixir
Hex - Elixir - MIT - Updated 7 months ago - 6 stars
balanced 3.1.0
Balanced API for Elixir
Hex - Elixir - MIT - Updated 4 months ago - 1 stars
bson 0.4.2
BSON implementation for Elixir
Hex - Elixir - MIT - Updated 6 months ago - 6 stars
message_pack 0.1.4
MessagePack Implementation for Elixir
Hex - Elixir - MIT - Updated 6 months ago - 20 stars
mongo 0.5.0
MongoDB driver for Elixir
Hex - Elixir - MIT - Updated 6 months ago - 29 stars
веселые картинки развлекательные гифки интресные факты смешные видео смешные истории из соцсетей