class: center, middle # A Chat with Sinatra Felix C. Stegerman `
` .small[2013-12-05] --- # What is Sinatra? According to Wikipedia: > Sinatra is a free and open source software web application library and domain-specific language written in Ruby. It is an alternative to other Ruby web application frameworks such as Ruby on Rails, Merb, Nitro and Camping. It is dependent on the Rack web server interface. > Designed and developed by Blake Mizerany, Sinatra is small and flexible. It does not follow the typical model-view-controller pattern used in other frameworks, such as Ruby on Rails. Instead, Sinatra focuses on "quickly creating web-applications in Ruby with minimal effort." Other micro frameworks inspired by Sinatra: * compojure (clojure) * express (javascript, node.js) * flask (python) * scalatra (scala) --- # What does Sinatra look like? ```ruby require 'sinatra' get '/hi' do "Hello World!\n" end ``` ``` $ gem install sinatra $ ruby hi.rb == Sinatra/1.4.4 has taken the stage on 4567 ... Listening on localhost:4567, CTRL+C to stop ``` ``` $ curl localhost:4567/hi Hello World! ``` --- # Some HTTP ``` # input prefixed with/ "> ", output w/ "< " $ nc -C localhost 4567 > GET /hi HTTP/1.1 > < HTTP/1.1 200 OK < Content-Type: text/html;charset=utf-8 < Content-Length: 13 < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Connection: keep-alive < Server: thin 1.6.1 codename Death Proof < < Hello World! ^D ``` ``` $ curl -v localhost:4567/hi ``` See also the chromium/firefox developer tools. --- # HTTP Methods and REST ```ruby get '/foos' do # show a resource (e.g. list of foos) haml :foos, locals: { foos: Foo.all } end get '/foo/:id' do # show a resource (e.g. specific foo) Foo.find(params[:id]).to_json end post '/foo' do # submit data (e.g. form) or create a resource end put '/foo/:id' do # create or update a resource end delete '/foo/:id' do # remove a resource end ``` --- # Routes, Views, Templates ```ruby get '/hello/:name' do |name| "Hello #{name}!" end ``` ```ruby get '/' do haml :index end ``` ```ruby get '/time' do erb 'The time is: <%= Time.now %>' end ``` ```ruby before do puts "the current request is: #{request.inspect}" end ``` Static files served from `public` folder. --- # Sinatra, Rack, ... ![](rack.svg) --- # Rack ```ruby run -> env { [200, {}, ['Hello, Rack!', "\n"]] } # object.call(env) --> [status, headers, body] ``` ``` run -> env { req = Rack::Request.new env Rack::Response.new.finish do |res| res['Content-Type'] = 'text/plain' res.status = 200 res.write "Parameters sent: #{req.params.inspect}\n" end } ``` ``` $ curl "localhost:9292?foo=42&bar=37" Parameters sent: {"foo"=>"42", "bar"=>"37"} $ curl -X POST localhost:9292 -d 'this=awesome' Parameters sent: {"this"=>"awesome"} ``` You can use `config.ru` and `rackup`. --- # Middleware ``` request --> middleware --> response request --> middleware --> app --> response request --> middleware --> response `-> app -^ ``` ```ruby use Rack::Auth::Basic, "Restricted Area" do |username, password| username == 'admin' and password == 'secret' end get '/' do 'You can only see this when logged in.' end get '/secret' do 'Welcome!' end ``` --- # Chatting with Sinatra ```ruby set :server, :thin set connections: [] get '/stream' do content_type 'text/event-stream' stream(:keep_open) do |out| settings.connections << out out.callback { settings.connections.delete out } end end post '/say' do msg = request.body.read settings.connections.each { |out| out << msg << "\n" } "message sent\n" end ``` ``` curl localhost:4567/stream ``` ``` curl -X POST localhost:4567/say -d 'Hello, Stream!' ``` --- # Ubuntu, Ruby, Environment, Gems, Bundler ``` $ sudo aptitude install git ruby1.9.1-full $ update-alternatives --config ruby # to set default ruby $ update-alternatives --config gem # and gem $ export GEM_HOME="$HOME/.gem/ruby/1.9.1" $ export PATH="$GEM_HOME/bin:$PATH" $ gem install bundler ``` ``` $ git clone https://github.com/obfusk/achatwithsinatra.git $ cd achatwithsinatra $ bundle $ rackup -p 8888 ``` ``` $ xdg-open http://localhost:8888 ``` --- class: center, middle # Demo: building a simple chat app --- # Links * https://github.com/obfusk/achatwithsinatra * http://achatwithsinatra.herokuapp.com * http://obfusk.github.io/achatwithsinatra * http://www.sinatrarb.com * http://en.wikipedia.org/wiki/Sinatra_%28software%29 * http://sinatra-book.gittr.com * http://rubylearning.com/blog/a-quick-introduction-to-rack * http://rack.rubyforge.org/doc/SPEC.html