learning curve breakthrough: part 1

0 views
Skip to first unread message

Phil Pirozhkov

unread,
Mar 14, 2009, 6:37:29 AM3/14/09
to Ryan framework
To skip "read all the code" step, i'm going to write a 5 min tutorial
on how
Ryan (and most other web frameworks do work)

Let's begin with directory structure that i've recently rearranged a
bit.

application_example - should tell for itself; contains controllers,
view, images and javascript
behavior - test/spec/behavior of different Ryan parts
bin - runnable ryan file
ebin - compiled erlang files. hope some day they will disappear
src
behave - test/spec/behavior utility. currently non-functional
core - controller, session, ryan. core functionality
retem - template engine. quite limited currently, but works fine
(and fast)
third party - different dependencies i had to include
erlang_couchdb - Ryan doesn't make any use of it and i'm not sure
CouchDB will fit, i like some others DBs much more
leex - lexical scanner for Retem templates
yaws - yaws include files


Okay, where to begin?
Prerequisites:
Erlang/OTP R12B-3 or higher http://www.erlang.org/download.html
Reia programming language http://github.com/tarcieri/reia
YAWS 1.77 or higher http://yaws.hyber.org
Rake 0.8 or higher http://github.com/jimweirich/rake

if you are looking at directory structure i assume you've cloned Ryan
from github already.
It's a pity, but currently to build Ryan it's required to have Ruby's
Rake installed.
Hope some day Make will be used instead to eliminate this odd
dependency.
Thus:
sudo rake install
(install task both builds and installs, just to type less)

What it does? It compiles .erl Erlang source files into .beam files,
that can be loaded by Reia,
copies them to (typically) /usr/local/lib/erlang/lib/ryan/ebin
It copies src/core files to /usr/local/lib/erlang/lib/ryan/
And bin/ryan to /usr/local/bin

Take a look at bin/ryan, the first row here tells the shell that this
file should
be run using:
#!/usr/bin/env reia

reia executes any .re file it is provided with
Please, don't compile Reia files, it's considered incorrect
File load time will get faster some day

!Be sure you run ryan from application_example folder, it will fail
otherwise

What bin/ryan does?
it loads controller.re, session.re, retem.re and ryan.re
it loads startup.re file from current folder. This is application/site
initialization (empty in example)
it creates in-memory ETS tables (to store session/compiled templates
data)
and runs yaws_shim on port 8001 (can be overrided in command line with
-p <port> option)

Okay, let's proceed to yaws_shim.erl (in Erlang, but fairly simple if
you look at it)
The main thing is on top.
out(Arg) is the method our powerful backed server (YAWS) calls when
someone
accesses our application at http://localhost:8001/app
It passes Arg, and we split this Arg to:
Cookie (session id is stored here)
Method: POST/GET/DELETE/PUT et c
PathParts: /app/todo/today becomes [:app, :todo, :today]
Params: /app/todo/today?aaa=123&bbb=345 gives {:aaa => 123, :bbb =>
345}

SessionToken: we're getting Cookie named 'sid', and if it isn't there,
creating it responding
using whis token.

What's that?
Result = reia_erl:r2e(reia:apply('Ryan', out, [Abs_Path, Method,
PathParts, Token, Params])),
This is the way we are getting back to code written in a language
we're dealing with mostly: Reia. We are calling module Ryan's method
'out', passing it all the given parameters.
This method resides in /src/core/ryan.re to be precise.

What happens in Ryan.out method?
we are trying to understand which method of which controller to call.
routing is pretty simple currently, it can be found in the bottom of
Ryan module.
if the request parts is one element long, we're heading Home
controller and calling .index on it
if the request parts is two elements long ([:app, :todo] for example),
we're heading to specified controller and its .index method
Otherwise we're heading to specified controller and method

out check, if there is a Session object associated with session token,
and if there' none, creates one (that contains an empty hash by
default):
session = Sessions.get(session_token)

Next, we are creating a controller instance and invoking the required
method on it:
result = page(controller, action, session, cp(parameters))

odd (_h, s, ns) = erlang::now()
rows just mean that we are measuring time used to process request

and, the last row of out method, we are returning the result of
controller's work to YAWS server

Next time i will tell how Controllers work, how templates work et c
Do not hesitate to ask

Phil


Reply all
Reply to author
Forward
0 new messages