A thin layer above Yaws to make web development with Yaws easier
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Ale is a web framework for Yaws to make web development with Yaws easier.

It provides:
* Sinatra-like routes (http://github.com/sinatra/sinatra)
* i18n
* Distributed memory caching for pages, actions, fragments, and objects
* Some conventions

It uses:
* Yaws:    http://wiki.github.com/klacke/yaws
* Log4erl: http://github.com/ahmednawras/log4erl
* Gettext:
* Cherly:  http://github.com/cliffmoon/cherly

You should use Log4erl instead of error_logger:

== Install and Create New Project

Install Ale and libraries listed in "It uses" in the above section to Erlang
lib directory.

There's no "generate" script. To create a new project, simply copy "skel"
directory to some place and modify.

== Routes and path

A route maps method and path to controller and action. Routes are defined in
controllers as a module attribute.


	get,    "/articles",          index,
	get,    "/articles/:id",      show,
	get,    "/articles/new",      new,
	post,   "/articles",          create,
	get,    "/articles/:id/edit", edit,
	put,    "/articles/:id",      update,
	delete, "/articles/:id",      delete

index() -> ...
show()  -> Id = list_to_integer(ale:params(id))...

Function names can be used in before action filters.

Use path to generate path (io list) back from controller, action, and params:

ale:path(articles, index)      % => ["/", "articles"]
ale:path(articles, show, [1])  % => ["/", "articles", "/", "1"]

== c_application

This controller defines common functionalities for all other controllers:
* error_404 and error_500, these functions do not use layout to avoid the case
  there is error in the layout
* Layout
* Filters

== Process Dictionary

Each HTTP request is served by one process.

Before filters -> Action -> View -> Layout.

Process dictionary is used to pass variables from a layer to layers after it.
Use ale:app(Key, Value) to put and ale:app(Key) to get.

Special keys for ale:app/1:
* controller
* action
* content_for_layout
* script

For the caching to work properly, you should not change things after putting them
to the process dictionary.

== Action and View

Each request is processed by a separate process. For convinience, output to Yaws
is not forced to be the last line of your action. Use ale:yaws and ale:app to
put things to namespaces in the process dictionary. Things in the "yaws"
namespace will be collected and sent to Yaws.

If your controller is c_hello and action is world, v_hello_world:render/0 will
be called. If you want to use a view other than the default view, in your action
call ale:view(Action) or ale:view(Controller, Action).

If there is no default view or the specified view does not exist, no view will
be called. If you do not want to use a view, just don't create the default view,
or call ale:view(undefined). In this case layout will also not be called.

If you want to send something directly to Yaws, call ale:view(undefined) and call
ale:yaws/2-4. See http://yaws.hyber.org/yman.yaws?page=yaws_api.

== Layout

To output your view with a layout, call ale:layout(LayoutModule).
LayoutModule:render/0 will be called. To get the rendered view, in your layout
call ale:app(content_for_layout).

== JavaScript

Call ale:script(Script) to add Script to the process dictionary. Near the end of
your layout, call ale:script(). ale:script(Script) can be called many times to
add many script fragments.

== Before Filter

c_application or any controller can define
before_filter(Controller, Action, Args). To halt the processing chain, this
function should return true.

== Session


== Cache

Page, action, fragment, and object are all cached in memory. The advantage of
caching pages in memory instead of on disk is that expiration time can be specified
for pages. For a certain action, types of caching should be mutual exclusive,
e.g. if the action is already set to be page cached then it should not also set
as action cached.

== Tips

When developing, to compile and reload code after a change, from EShell run
ale:sync()., it will call make:all([load]), which runs Emakefile to compile then
reload. make is a standard module of Erlang.