A Ruby programozási nyelv

Sinatra keretrendszer

Bevezetés

A Sinatra egy DSL, ami lehetővé teszi számunkra, hogy minimális energiabefektetéssel és gyorsan írhassunk egyszerű webalkalmazásokat.

A Rails vetélytársának nem igazán tekinthető, az ugyanis jóval összetettebb felépítésű és szélesebb körben használt keretrendszer, amit folyamatosan fejlesztenek és optimalizálnak.

Ellentétben a Rails-szel, a Sinatra-t akkor érdemes használni, ha az elkészítendő webalkalmazás kis méretű és egyszerű. Ezen alkalmazások esetében a Rails használata túlkapás lehet.

Gyors kezdés

Egy egyszerű példa: Hello World!

A myapp.rb fájl tartalma:

# myapp.rb require 'sinatra' get '/' do 'Hello world!' end

A gem feltelepítése:

gem install sinatra

Futtatás:

ruby myapp.rb

Az alkalmazást a http://localhost:4567 url-en érhetjük el.

Felépítés

Route-ok felépítése

A Sinatra-ban egy route egy http metódus és egy url minta párjaként áll elő. Minden egyes route-hoz tartozik egy blokk. A route-hoz tartozó blokkban definiálhatjuk a megfelelő http kérésekre vonatkozó reakciót, azaz a blokkban adhatjuk meg, hogy milyen választ adjon a szerver az egyes kérésekre.

get '/' do .. show something .. end post '/' do .. create something .. end put '/' do .. replace something .. end patch '/' do .. modify something .. end delete '/' do .. annihilate something .. end options '/' do .. appease something .. end link '/' do .. affiliate something .. end unlink '/' do .. separate something .. end

A route-ok a definiciójuk sorrendjében jutnak érvényre. Tehát, ha egy olyan http kérés érkezik a szerverre, ami két route-nak is megfeleltethető lenne a típusa és a mintája alapján, akkor a sorrendben előbb definiált route-hoz tartozó blokk értékelődne ki és az adná meg a választ a kérésre.

Egy webalkalmazás esetében gyakran előfordul, hogy az urlnek tartalmaznia kell nevesített paramétereket. Ahogy a következő kódrészletből is látható, a mintában a ":" karakterrel jelölhetjük meg, hogy mi legyen paraméternév, a blokkon belül pedig a params nevű asszociatív tömbből kérhetjük le a változó értékét.

get '/hello/:name' do # matches "GET /hello/foo" and "GET /hello/bar" # params[:name] is 'foo' or 'bar' "Hello #{params[:name]}!" end

A nevesített paramétereket a blokk változójaként is elérhetjük.

get '/hello/:name' do |n| # matches "GET /hello/foo" and "GET /hello/bar" # params[:name] is 'foo' or 'bar' # n stores params[:name] "Hello #{n}!" end

A route paraméterek lehetnek joker karakterek is.

get '/say/*/to/*' do # matches /say/hello/to/world params[:splat] # => ["hello", "world"] end get '/download/*.*' do # matches /download/path/to/file.xml params[:splat] # => ["path/to/file", "xml"] end

Ezek is használhatók blokk-változóként.

get '/download/*.*' do |path, ext| [path, ext] # => ["path/to/file", "xml"] end

A route minták leírhatók a Regexp osztály példányai segítségével is.

get %r{/hello/([\w]+)} do "Hello, #{params[:captures].first}!" end

Ebben az esetben is van lehetőség a blokk-változók használatára is.

get %r{/hello/([\w]+)} do |c| "Hello, #{c}!" end

A route minták esetében opcionális paraméterek kezelésére is szükség lehet.

get '/posts.?:format?' do # matches "GET /posts" and any extension "GET /posts.json", "GET /posts.xml" etc. end

Az egyéb, nem nevesített paraméterek kezelése szintén a params nevű asszociatív tömb segítségével végezhető el.

get '/posts' do # matches "GET /posts?title=foo&author=bar" title = params[:title] author = params[:author] # uses title and author variables; query is optional to the /posts route end

Egyéb feltételek

A route-ok esetében egyéb korlátozások is szükségesek lehetnek. Például megadhatjuk, hogy egy adott route-hoz tartozóan csak html választ vagyunk hajlandóak adni, míg ugyanazon mintának megfelelő kérésre json választ egy másik route segítségével adunk.

get '/', :provides => 'html' do haml :index end

Természetesen definiálhatunk saját feltételeket is. A következő példában a feltételünk dinamikusan változik. Annak függvényében választja az egyik, vagy a másik blokkot, hogy a rand metódus segítségével generált érték nagyobb-e a példában megadott 0.1 értéknél.

set(:probability) { |value| condition { rand <= value } } get '/win_a_car', :probability => 0.1 do "You won!" end get '/win_a_car' do "Sorry, you lost." end

A feltételek kezelése lehetővé teszi a felhasználók egyszerű authentikációját is.

set(:auth) do |*roles| # <- notice the splat here condition do unless logged_in? && roles.any? {|role| current_user.in_role? role } redirect "/login/", 303 end end end get "/my/account/", :auth => [:user, :admin] do "Your Account Details" end get "/only/admin/", :auth => :admin do "Only admins are allowed here!" end

Statikus fájlok

A statikus fájlokat alapértelmezetten a rendszer a ./public könyvtárban keresi, de ez konfigurálható.

set :public_folder, File.dirname(__FILE__) + '/static'

Fontos megjegyezni, hogy a publikus könyvtár neve nem része a könyvtárban található fájlok url-jének. Például a ./public/css/style.css a http://example.com/css/style.css url-en válik elérhetővé.

Nézetek, sablonok

Az alkalmazás a sablonokat a views könyvtárban keresi. Minden egyes sablonnyelvet a saját kiértékelő metódusával alkalmazhatunk.

get '/' do erb :index end

Az utóbbi példa a views/index.erb fájlt rajzolja ki a kérésre adott válaszként.

A sablon neve helyett a sablon tartalma direktben is megadható.

get '/' do code = "<%= Time.now %>" erb code end

Szűrők

A before és after szűrők lefutnak minden egyes olyan kérés előtt és után, amiknek a környezete megfelel a szűrőben megadottnak. A következő példában látható szűrő például lefut minden olyan kérés előtt, aminek url-je illeszthető a '/protected/*' mintára.

before '/protected/*' do authenticate! end

A szűrőkben állíthatunk be példány változókat, amik módosíthatják a kérést és a választ egyaránt.

before do @note = 'Hi!' request.path_info = '/foo/bar/baz' end get '/foo/*' do @note #=> 'Hi!' params[:splat] #=> 'bar/baz' end

Segéd metódusok

Gyakran ismételt folyamatokat érdemes segéd metódusokként definiálni, így csökkentve a redundanciát.

helpers do def bar(name) "#{name}bar" end end get '/:name' do bar(params[:name]) end

Egy egyszerű példa

Ez egy egyszerű példaalkalmazás a Sinatra keretrendszer használatára.

A futtatáshoz telepíteni szükséges a sinatra gem-et.

Az adatok egy fájlban tárolódnak YAML formátumban. Az adatokat tároló fájl inicializálásához a következő parancsot szükséges futtatni a program gyyökérkönyvtárában:

ruby initialize_data.rb
Az alkalmazás elindításához a következő parancsot szükséges kiadni a program gyökérkönyvtárában:
ruby sinatra_example.rb

Ezt követően a rendszer a http://0.0.0.0:4567 url-en érhető el. Az inicializálás során létrehozott felhasználó neve: "Test Admin", ezzel a névvel be lehet jelentkezni a rendszerbe.

Forráskód letöltése