sinatra
DESCRIPTION
Charla brindada en Locos x Rails en Buenos Aires, Argentina, el 4 de abril de 2009 sobre el framework web Sinatra.Breve descripción del framework y sus capacidades, una muy breve introducción a Rack y cómo funciona, y una muestra rápida de los Rails Metals, y de cómo integrar aplicaciones sinatra a nuestras aplicaciones en Rails.TRANSCRIPT
Sinatra
Nicolás Sanguinetti
foca
http://entp.com
¿Qué es?
Un ejemplo
y lo guardamos como hello.rb
require "rubygems"require "sinatra"
get "/hello" do "<h1>Hello World</h1>"end
Un ejemplo
$ gem install sinatra$ ruby hello.rb== Sinatra has taken the stage ...>> Listening on 0.0.0.0:4567
Un ejemplo
Features
URLs Parametrizablesget "/hello/:name" do |name| # también con params[:name] "<h1>Hello #{name}</h1>"end
Vistas
y en views/hello.erb
get "/hello/:name" do |name| @name = name erb :helloend
<h1>Hello <%= @name %></h1>
Layoutsponemos en views/layout.erb
y todas nuestras vistas se renderean “adentro” de esta (reemplazando al yield)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"><head> <title>Hello <%= @name || "World" %></head><body> <%= yield %></body></html>
HTTP
get "/..." do "..."end
post "/..." do "..."end
put "/..." do "..."end
delete "/..." do "..."end
Pero PUT y DELETE...
<form action="/put/action" method="post"> <input type="hidden" name="_method" value="put"> ...</form>
Blog en 15 minutos*
* para valores relativos de 15
require "dm-core"require "do_sqlite3"load "lib/models.rb"
configure do DataMapper.setup(:default, "sqlite3:blog.db")end
(por ejemplo, DataMapper)
Usando un ORM con Sinatranecesitamos guardar los posts en algún lado, así que...
class Post include DataMapper::Resource property :id, Serial property :title, String, :nullable => false property :permalink, String, :nullable => false property :body, Text, :nullable => false before :valid?, :set_permalink has n, :comments private def set_permalink self.permalink = title.gsub(/\s+/, "-") endend
class Comment include DataMapper::Resource property :id, Serial property :post_id, Integer, :nullable => false property :author, String, :nullable => false property :body, Text, :nullable => false belongs_to :postend
lib/models.rb
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/" doend
get "/new" doend
post "/" doend
get "/:permalink" do |permalink|end
post "/:permalink/comments" do |permalink|end
delete "/:permalink" do |permalink|end
get "/:permalink/edit" do |permalink|end
put "/:permalink" do |permalink|end
Qué queremos en el blog?
get "/new" do @post = Post.new erb :newend
post "/" do @post = Post.new(params[:post])
if @post.save redirect "/#{@post.permalink}" else erb :new endend
Creemos un Post entonces
<form method="post" action="/"> <div><label for="post_title">Title</label> <input type="text" name="post[title]" id="post_title" value="<%= @post.title %>"></div> <div><label for="post_body">Your Article</label> <textarea id="post_body" name="post[body]" rows="20" cols="40"><%= @post.body %></textarea> </div> <div><button type="submit">Post new article</button> or <a href="/#{@post.permalink}">go back</a>.</div></form>
views/new.erb
get "/" do @posts = Post.all erb :indexend
Listando posts
views/index.erb
<h2>All Posts</h2>
<ul id="posts"><% for post in @posts %> <li class="post"> <h2> <a href="/<%= post.permalink %>"> <%= post.title %> </a> </h2>
<%= post.body %> </li><% end %></ul>
Un paréntesis: helpers!
helpers do def post_path(post) "/#{post.permalink}" endend
get "/:permalink" do |permalink| @post = Post.first(:permalink => permalink) erb :showend
Mostrando un post
views/show.erb
<h2> <a href="<%= post_path(@post) %>"> <%= @post.title %> </a></h2>
<%= @post.body %>
<div><a href="/">Go back to the list</a></div>
Parentesis: “partials”views/post.erb
views/post.erb<%= erb(:post, :layout => false, :locals => { :post => @post }) %><div><a href="/">Go back to the list</a></div>
<h2> <a href="<%= post_path(post) %>"> <%= post.title %> </a></h2>
<%= post.body %>
Comentariosget "/:permalink" do |permalink| @post = Post.first(:permalink => permalink) @comment = Comment.new erb :showend
post "/:permalink/comments" do |permalink| @post = Post.first(:permalink => permalink) @comment = @post.comments.build(params[:comment]) if @comment.save redirect post_path(@post) else erb :show endend
y en show.erb<div id="comments"> <ul> <% for comment in @post.comments %> <li><p><%= escape_html comment.body %></p> <address>—<%= escape_html comment.author %></address></li> <% end %> </ul> <form method="post" action="<%= post_path(@post) %>/comments"> <div><label for="comment_author">Name</label> <input type="text" name="comment[author]" id="comment_author" value="<%= @comment.author %>"></div> <div><label for="comment_body">Your Comment</label> <textarea id="comment_body" name="comment[body]" rows="6" cols="40"><%= @comment.body %></textarea></div> <div><button type="submit">Leave Comment</button></div> </form></div>
Embelleciendo un poco...ponemos en views/layout.erb
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link href="/styles.css" rel="stylesheet" type="text/css"> <title><%= page_title %></title> </head> <body> <div id="header"> <h1><%= page_title %></h1> </div> <%= yield %> </body></html>
Embelleciendo un poco...
helpers do def post_path(post) "/#{post.permalink}" end def page_title if @post && [email protected]_record? "Awesome Blog | #{@post.title}" else "Awesome Blog" end endend
Embelleciendo un poco...ponemos en views/layout.erb
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link href="/styles.css" rel="stylesheet" type="text/css"> <title><%= page_title %></title> </head> <body> <div id="header"> <h1><%= page_title %></h1> </div> <%= yield %> </body></html>
Embelleciendo un poco...
public/styles.css
y editar y borrar...para la próxima
es una interfazentre servidores
y frameworks
class RackIsEasy def initialize(app) @app = app end
def call(env) [200, {"Content-Type" => "text/html"}, ["Ok"]] endend
class AndRackIsPotentiallyDumb def initialize(app) @app = app end
def call(env) @app.call(env) endend
app_4
app_1
app_2
app_3
HTTP
App
Middlew
ares
http://mwrc2009.confreaks.com/ – Jon Crosby
para qué sirve eso?
class MightyCache def initialize(app) @app = app end
def call(env) if response = cache_hit?(env) response else cache_store(env, @app.call(env)) end end
# def cache_hit?, cache_store, etcend
por ejemplo, caching:
Sinatra is on crack
última cosa
prometo que ya me voy
\m/
Rails Metalsen app/metal/api.rb
class Api def self.call(env) if env["PATH_INFO"] =~ /^\/stuff.json/ [200, {"Content-Type" => "application/json"}, "{}"] else [404, {"Content-Type" => "application/json"}, ""] end endend
Sinatra on RailsHard Metal Frank Sinatra
El ejemplo anterior:
class Api < Sinatra::Base get "/stuff", :provides => "application/json" do "{}" endend
y en config/environment.rb
config.gem "sinatra"
Questions?Preguntas?
http://github.com/foca/[email protected]