Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Web Development with Sinatra

Bob Nadler
December 10, 2012

Web Development with Sinatra

Fundamentals and some "advanced" topics for writing web applications using Ruby's Sinatra library.

Bob Nadler

December 10, 2012
Tweet

Other Decks in Programming

Transcript

  1. “Sinatra is a DSL for quickly creating web applications in

    Ruby with minimal effort.” - sinatrarb.com/intro
  2. “A library is essentially a set of functions that you

    can call... Each call does some work and returns control to the client.” “A framework embodies some abstract design, with more behavior built in... you need to insert your behavior into various places in the framework.” http://martinfowler.com/bliki/InversionOfControl.html Martin Fowler
  3. Sinatra allows you to structure your application to fit the

    problem you’re trying to solve instead of the other way around.
  4. Simplest Example require 'sinatra' get '/hi' do "Hello World!" end

    $ gem install sinatra $ ruby hi.rb == Sinatra has taken the stage .. >> Listening on 0.0.0.0:4567
  5. Fundamentals Anatomy of a Route Handler HTTP Verb get post

    put delete patch URL Behavior get '/hello/:name' do "Hello, #{params[:name]}" end Parameters
  6. Fundamentals The First Sufficient Match Wins get '/*' do "NOM

    NOM NOM" end get '/specific' do "I'll never be matched... you'll won't see me!" end
  7. Fundamentals Views: Inline Templates require 'sinatra' get '/index' do erb

    :index end __END__ @@index <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Inline Template</title> </head <body> <h1>It Worked!</h1> </body> </html> ERB by default, but any templates supported by Tilt will work Each inline template must have a unique name
  8. Fundamentals Views: External Templates Just place your templates in a

    /views folder and Sinatra will pick them up; you’re route handlers stay the same
  9. Fundamentals Views: Passing Data get '/home' do @name = 'John

    Doe' erb :home end __END__ @@home <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Inline Template</title> </head <body> <h1><%= @name %></h1> </body> </html>
  10. Fundamentals Helpers helpers do def link(name) case :name when :about

    then '/about' when :index then '/index' else "/page/#{name}" end end # in your view template <a href="<%= link :about %>">About</a> # -- OR -- # define helpers as methods in a module module MyHelpers # helper methods end helpers MyHelpers
  11. Fundamentals Caching get '/cache' do expires 3600, :public, :must_revalidate "This

    page rendered at #{Time.now}." end See http://www.mnot.net/cache_docs/ for an explanation of HTTP caching options
  12. Fundamentals Sessions configure do enable :sessions end get '/set' do

    session[:foo] = Time.now "Session time was set." end get '/fetch' do "Session value: #{session[:foo]}" end get '/unset' do session.clear redirect '/fetch' end
  13. Fundamentals Testing with rack-test require 'my_sinatra_app' require 'test/unit' require 'rack/test'

    class MyAppTest < Test::Unit::TestCase include Rack::Test::Methods def app Sinatra::Application end def test_my_default get '/' assert_equal 'Hello World!', last_response.body end def test_with_params get '/meet', :name => 'Frank' assert_equal 'Hello Frank!', last_response.body end def test_with_rack_env get '/', {}, 'HTTP_USER_AGENT' => 'Songbird' assert_equal "You're using Songbird!", last_response.body end end
  14. Advanced Topics Modular vs. “Classic” “For some reason, it is

    a common misconception that modular applications are superior to classic applications, and that really advanced users only use modular style... This is utter nonsense and no one on the Sinatra core team shares this view. Sinatra is all about simplicity and if you can use a classic application, you should.” -- Sinatra Up and Running
  15. Advanced Topics Reasons to Use Modular you don’t want to

    pollute the Object namespace (writing a Gem) combining multiple Sinatra apps in a single process use Sinatra app as middleware
  16. Advanced Topics Simplest Modular Example require 'sinatra/base' class MyApp <

    Sinatra::Base get '/hi' do "Hello World!" end # Only start the server if the file # has been executed directly # # $0 is the executed file # __FILE__ is the current file run! if __FILE__ == $0 end
  17. Advanced Topics Running with Rack: Rackup File # In a

    file named my_app.rb require 'sinatra/base' class MyApp < Sinatra::Base get '/hi' do "Hello World!" end end # in a separate file named config.ru require './my_app' run MyApp # launch the server using # rackup command or shotgun
  18. Advanced Topics Running with Rack: Middleware Chain # In a

    file named my_app.rb require 'sinatra/base' class Foo < Sinatra::Base get('/foo') { 'foo' } end class Bar < Sinatra::Base get('/bar') { 'bar' } use Foo end # config.ru require 'my_app' run Bar # Or Foo and Bar can be in separate files # remember... it's just Ruby!
  19. Advanced Topics Running with Rack: Cascade require 'sinatra/base' class Foo

    < Sinatra::Base get('/foo') { 'foo' } end class Bar < Sinatra::Base get('/bar') { 'bar' } end # config.ru require 'my_app' run Rack::Cascade, [Foo, Bar] # Differences: # * _slightly_ better performance, but only if you have a lot of endpoints # * you can use any Rack app (like Rails)
  20. Use Cases Prototyping Web Apps API Server for iOS /

    Android / JavaScript Apps HTML5 Mobile Apps
  21. Resources • http://rubydoc.info/gems/sinatra/file/README.rdoc • http://www.sinatrarb.com/documentation • Sinatra: Up and Running

    (http://shop.oreilly.com/product/0636920019664.do) • http://stackoverflow.com/questions/148747/what-is-the-difference-between-a- framework-and-a-library • http://www.quora.com/Software-Engineering/Whats-the-difference-between-a- library-and-a-framework • http://martinfowler.com/bliki/InversionOfControl.html • http://www.mnot.net/cache_docs/ • https://github.com/bnadlerjr/sidestep • https://github.com/bnadlerjr/leaflet • https://github.com/bnadlerjr/sinatra-linkedin • https://github.com/bnadlerjr/fuelyo • http://rubygems.org/gems/middleman