Sinatra: a Micro-framework for Web Applications http://www.sinatrarb.com/ Kevin Reiss Office of Library Services
Sinatra: a Micro-framework for Web Applications
http://www.sinatrarb.com/
Kevin ReissOffice of Library Services
What is Sinatra?
• A web application micro-framework• Minimal stack framework
• A ruby Domain Specific Language (DSL)
• A ruby “rack” application
• A ruby “gem”• Gems are the ruby equivalent of• Perl modules• PHP PEAR• Managing gems is very easy
- Gem install sinatra is all you need
Why Sinatra?
• It is lightweight
• Built on the rack “gem”• Rack is a generic ruby library for building web applications
• It is nicely pluggable within other applications• Rails3 has featured support for sinatra apps as middleware
• Good tool for creating REST-like interfaces
• Supports many different template syntaxes
• It has it’s own web server: default thin
• Convention over Configuration: the Ruby Framework Way
Hello World?
# hello_world.rb require 'sinatra' # a single sinatra block with a return valueget '/' do 'Hello world!' # return the string “Hello World”end
To run the app:> ruby hellow_world.rb
Second Hello World App
• Sinatra configuration
• Sinatra routes
• Sinatra helpers
• Watch your Request values
Sinatra: Helpers, Routes, and Blocks
helpers do def format_title(name) name.capitalize # your return value endEnd
get '/library/:department' do @title = "#{format_title(params[:department])} Department".strip haml :department # invoke a templateend
Views with Sinatra
• Standard convention• Views always go in the “views” directory• Templates marked “layout.ext” are automatically used
as wrappers for “content-like templates” like “mycustomdisplay.ext”
• Static files (stylesheets, images, etc.) are served up out of the “public” directory
• Support a wide variety of template options to generate XHTML, HTML5, XML, etc.
• Can easily define custom formats• Integration with RACK makes it easy to deal with the
parts of an HTTP Request
HAML Templates
• HAML – HTML Templates for the Lazy
• Also bundled with a CSS Template: SASS%html{:"xml:lang"=>"en"} %head %title My Library Web: #{@title} %link{:type=>"text/css",:rel=>"stylesheet",:media=>"screen",:href=>"/stylesheet.css"} %body #pageContent #header %ul.nav %li %a{:href=>"/"} Home #body =yield #footer %p Office of Library Services
Where is the Registry?
• Set configuration options and constants easily
• Sinatra’s integration with rack makes it easy to access and manipulate the contents of the http.request associated
What about Testing?• Unit tests are built into rack
set :environment, :test
class LibraryTest < Test::Unit::TestCase
def test_it_says_hello_world browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/' assert browser.last_response.ok? assert_equal '<h1>Hello World!</h1>', browser.last_response.body end
def test_it_says_hello_to_a_department browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/library/ill' assert browser.last_response.body.include?('ill') endend
Deployment Options
• Launch Locally with ruby thin web server• This is built into the application
• Publish directly to heroku
• Launch via apache• proxy_balancer module• passenger module
• ngnix
Heroku Features
• Read-only filesystem
• Installed as a ruby gem
• Integrated with git and ssh
• Free for low-volume applications
• Add-ons to expand functionality• Memcache• Databases,DNS,
• heroku logs
• Good documentation
• Not just sinatra, rails and any other rack-based application
• Similar to the “Google App Engine”
Heroku Deployment
• Ruby Platform as a Service – http://heroku.com/
• Rails, Sinatra, generic Rack Applications
• Integrated directly with git version to control
• To Deploy:• create “config.ru” file – defines your rack application• create .gems file – defines libraries your app requires• git init• git add .• git commit –m “Initial Commit”• heroku create• git push heroku master
Thin Server Configuration
--- chdir: /home/kreiss/ruby/lookup/rackup: /home/kreiss/ruby/lookup/config.ru environment: productionaddress: 127.0.0.1port: 5000timeout: 30log: /home/kreiss/ruby/lookup/log/thin.logpid: /home/kreiss/ruby/lookup/tmp/pids/thin.pidmax_conns: 1024max_persistent_conns: 512require: []wait: 30servers: 3daemonize: true
An Actual Application
• Standard number checker
• Wrapper for our web services provided by our ILS
• Embed this as a web service in other application/scripts
REST-Like Interface
• Output multiple formats• JSON• Custom XML with builder gem
• XML parsing handled by the nokogiri ruby gem
More Complicated Sample Route
get '/:campus/isbn/:isbn' do lookup_base = is_valid_sublibrary(params[:campus]) @number = is_valid_isbn(params[:isbn]) @type = "ISBN" @title = “#{@type}: #{@number} for campus #{lookup_base}" @items = standard_lookup(@number, "bath.isbn", lookup_base) if params[:format] == "xml" builder :bib elsif params[:format] == "json" @items.to_json else haml :standard endend
Heroku Deployment
• 486 curl http://cunylookup.heroku.com/laguardia/barcode/33324001754295• 487 curl http://cunylookup.heroku.com/city/isbn/0800630807• 488 curl http://cunylookup.heroku.com/city/isbn/0800630807?format=xml• 489 curl http://cunylookup.heroku.com/city/isbn/0800630807?format=json• 490 curl http://cunylookup.heroku.com/cun01/isbn/0800630807• 491 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=json• 492 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml• 493 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml• 494 curl http://cunylookup.heroku.com/cun01/issn/1092-7735?format=xml• 495 curl http://cunylookup.heroku.com/city/issn/1092-7735?format=xml• 496 curl http://cunylookup.heroku.com/laguardia/issn/1092-7735?format=xml• 497 curl http://cunylookup.heroku.com/laguardia/lccn/96042502?format=xml• 498 curl http://cunylookup.heroku.com/cun01/lccn/96042502?format=xml
Gotchas
• Ruby 1.8 v. Ruby 1.9• Heroku supports both• Gems need to be called differently in ruby 1.8
• Name your gems sensibly – annoying rubyism• Dalli: name for memcache gem• Nokogiri: name for xml processing gem
• Sinatra vs. Sinatra Base• If you plan to use as middleware in another ruby
app you need to define your application with sinatra base
Other frameworks in Libraries
• Rails (Blacklight)
• PHP Zend (Omeka)
• Django (Solr front-end)
• Xerxes (Metasearch)
Drupal Platform
• Services
• Views datasource
• Drupal Workflow building capabilities• Workflow module• New workbench toolkit
• D7 Rest Server
Code4lib Report
• Looks of repository middleware
Code4libNYC
• Suggestion to host day long event