35
Web Development with Sinatra

Web Development with Sinatra

Embed Size (px)

Citation preview

Page 1: Web Development with Sinatra

Web Development with Sinatra

Page 2: Web Development with Sinatra

What is Sinatra?

Page 3: Web Development with Sinatra

“Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort.”

- sinatrarb.com/intro

Page 4: Web Development with Sinatra

It’s a LIBRARY not a FRAMEWORK.

Page 5: Web Development with Sinatra

huh?

Page 8: Web Development with Sinatra

“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

Page 9: Web Development with Sinatra

Sinatra allows you to structure your application to fit the problem you’re trying to solve instead of the other way around.

Page 10: Web Development with Sinatra

Simplest Examplerequire '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

Page 11: Web Development with Sinatra

Road Map

• Fundamentals

• “Advanced” Topics

• Use Cases

Page 12: Web Development with Sinatra

FundamentalsAnatomy of a Route Handler

HTTP Verbgetpostput

deletepatch

URL

Behavior

get '/hello/:name' do "Hello, #{params[:name]}"end

Parameters

Page 13: Web Development with Sinatra

FundamentalsThe 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

Page 14: Web Development with Sinatra

FundamentalsHalting a Request

get '/halt' do "You will not see this output." halt 500end

Page 15: Web Development with Sinatra

FundamentalsRedirecting a Request

get '/search' do redirect 'http://www.google.com', 301end

Optional

Page 16: Web Development with Sinatra

FundamentalsViews: Inline Templatesrequire 'sinatra'

get '/index' do erb :indexend

__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

Page 17: Web Development with Sinatra

FundamentalsViews: External Templates

Just place your templates in a /views folder and Sinatra will pick them up; you’re route handlers stay the same

Page 18: Web Development with Sinatra

FundamentalsViews: Passing Dataget '/home' do @name = 'John Doe' erb :homeend

__END__

@@home

<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Inline Template</title></head<body> <h1><%= @name %></h1></body></html>

Page 19: Web Development with Sinatra

FundamentalsFilters

before do content_type :jsonend

after do "After filter called"end

Page 20: Web Development with Sinatra

FundamentalsHelpershelpers do def link(name) case :name when :about then '/about' when :index then '/index' else "/page/#{name}" endend

# in your view template<a href="<%= link :about %>">About</a>

# -- OR --# define helpers as methods in a module

module MyHelpers # helper methodsend

helpers MyHelpers

Page 21: Web Development with Sinatra

FundamentalsConfiguration

configure :development do set :db, Sequel.sqlite('db/development.sqlite')end

configure :production do set :db, Sequel.connect(ENV['DATABASE_URL'])end

Page 22: Web Development with Sinatra

FundamentalsCaching

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

Page 23: Web Development with Sinatra

FundamentalsSessionsconfigure do enable :sessionsend

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

Page 24: Web Development with Sinatra

FundamentalsAttachments

before do content_type :txtend

get '/attachment' do attachment 'path/to/my-attachment.txt'end

Page 25: Web Development with Sinatra

FundamentalsTesting with rack-testrequire '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 endend

Page 26: Web Development with Sinatra

Advanced TopicsModular 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

Page 27: Web Development with Sinatra

Advanced TopicsReasons 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

Page 28: Web Development with Sinatra

Advanced TopicsSimplest Modular Examplerequire '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__ == $0end

Page 29: Web Development with Sinatra

Advanced TopicsRunning with Rack: Rackup File# In a file named my_app.rbrequire 'sinatra/base'

class MyApp < Sinatra::Base get '/hi' do "Hello World!" endend

# in a separate file named config.rurequire './my_app'run MyApp

# launch the server using# rackup command or shotgun

Page 30: Web Development with Sinatra

Advanced TopicsRunning with Rack: Middleware Chain# In a file named my_app.rbrequire 'sinatra/base'

class Foo < Sinatra::Base get('/foo') { 'foo' }end

class Bar < Sinatra::Base get('/bar') { 'bar' } use Fooend

# config.rurequire 'my_app'run Bar

# Or Foo and Bar can be in separate files# remember... it's just Ruby!

Page 31: Web Development with Sinatra

Advanced TopicsRunning with Rack: Cascaderequire 'sinatra/base'

class Foo < Sinatra::Base get('/foo') { 'foo' }end

class Bar < Sinatra::Base get('/bar') { 'bar' }end

# config.rurequire '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)

Page 32: Web Development with Sinatra

Advanced TopicsExtensions: LinkedIn Example

Page 33: Web Development with Sinatra

Use Cases

Prototyping Web Apps

API Server for iOS / Android / JavaScript Apps

HTML5 Mobile Apps

Page 34: Web Development with Sinatra

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