# Sinatra *æ³¨ï¼ æ¬ææ¸ã¯è±èªãã翻訳ãããã®ã§ããããã®å 容ãææ°ã§ãªãå ´åãããã¾ããææ°ã®æ å ±ã¯ãªãªã¸ãã«ã®è±èªçãåç §ãã¦ä¸ããã* Sinatraã¯æå°ã®å´åã§Rubyã«ããWebã¢ããªã±ã¼ã·ã§ã³ãææ©ãä½ãããã®[DSL](http://ja.wikipedia.org/wiki/ãã¡ã¤ã³åºæè¨èª)ã§ãã ``` ruby # myapp.rb require 'sinatra' get '/' do 'Hello world!' end ``` gemãã¤ã³ã¹ãã¼ã«ãã ``` shell gem install sinatra ``` 次ã®ããã«å®è¡ãã¾ãã ``` shell ruby myapp.rb ``` [localhost:4567](http://localhost:4567) ãéãã¾ãã Thinãããã°Sinatraã¯ãããå©ç¨ããã®ã§ã`gem install thin`ãããã¨ããè¦ããã¾ãã ## ç®æ¬¡ * [Sinatra](#sinatra) * [ç®æ¬¡](#ç®æ¬¡) * [ã«ã¼ãã£ã³ã°(Routes)](#ã«ã¼ãã£ã³ã°routes) * [æ¡ä»¶(Conditions)](#æ¡ä»¶conditions) * [æ»ãå¤(Return Values)](#æ»ãå¤return-values) * [ã«ã¹ã¿ã ã«ã¼ãã£ã³ã°ãããã£ã¼(Custom Route Matchers)](#ã«ã¹ã¿ã ã«ã¼ãã£ã³ã°ãããã£ã¼custom-route-matchers) * [éçãã¡ã¤ã«(Static Files)](#éçãã¡ã¤ã«static-files) * [ãã¥ã¼ / ãã³ãã¬ã¼ã(Views / Templates)](#ãã¥ã¼--ãã³ãã¬ã¼ãviews--templates) * [ãªãã©ã«ãã³ãã¬ã¼ã(Literal Templates)](#ãªãã©ã«ãã³ãã¬ã¼ãliteral-templates) * [å©ç¨å¯è½ãªãã³ãã¬ã¼ãè¨èª](#å©ç¨å¯è½ãªãã³ãã¬ã¼ãè¨èª) * [Haml ãã³ãã¬ã¼ã](#haml-ãã³ãã¬ã¼ã) * [Erb ãã³ãã¬ã¼ã](#erb-ãã³ãã¬ã¼ã) * [Builder ãã³ãã¬ã¼ã](#builder-ãã³ãã¬ã¼ã) * [Nokogiri ãã³ãã¬ã¼ã](#nokogiri-ãã³ãã¬ã¼ã) * [Sass ãã³ãã¬ã¼ã](#sass-ãã³ãã¬ã¼ã) * [SCSS ãã³ãã¬ã¼ã](#scss-ãã³ãã¬ã¼ã) * [Less ãã³ãã¬ã¼ã](#less-ãã³ãã¬ã¼ã) * [Liquid ãã³ãã¬ã¼ã](#liquid-ãã³ãã¬ã¼ã) * [Markdown ãã³ãã¬ã¼ã](#markdown-ãã³ãã¬ã¼ã) * [Textile ãã³ãã¬ã¼ã](#textile-ãã³ãã¬ã¼ã) * [RDoc ãã³ãã¬ã¼ã](#rdoc-ãã³ãã¬ã¼ã) * [AsciiDoc ãã³ãã¬ã¼ã](#asciidoc-ãã³ãã¬ã¼ã) * [Radius ãã³ãã¬ã¼ã](#radius-ãã³ãã¬ã¼ã) * [Markaby ãã³ãã¬ã¼ã](#markaby-ãã³ãã¬ã¼ã) * [RABL ãã³ãã¬ã¼ã](#rabl-ãã³ãã¬ã¼ã) * [Slim ãã³ãã¬ã¼ã](#slim-ãã³ãã¬ã¼ã) * [Creole ãã³ãã¬ã¼ã](#creole-ãã³ãã¬ã¼ã) * [MediaWiki ãã³ãã¬ã¼ã](#mediawiki-ãã³ãã¬ã¼ã) * [CoffeeScript ãã³ãã¬ã¼ã](#coffeescript-ãã³ãã¬ã¼ã) * [Stylus ãã³ãã¬ã¼ã](#stylus-ãã³ãã¬ã¼ã) * [Yajl ãã³ãã¬ã¼ã](#yajl-ãã³ãã¬ã¼ã) * [WLang ãã³ãã¬ã¼ã](#wlang-ãã³ãã¬ã¼ã) * [ãã³ãã¬ã¼ãå ã§ã®å¤æ°ã¸ã®ã¢ã¯ã»ã¹](#ãã³ãã¬ã¼ãå ã§ã®å¤æ°ã¸ã®ã¢ã¯ã»ã¹) * [`yield`ãä¼´ããã³ãã¬ã¼ãã¨ãã¹ãããã¬ã¤ã¢ã¦ã](#yieldãä¼´ããã³ãã¬ã¼ãã¨ãã¹ãããã¬ã¤ã¢ã¦ã) * [ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ã(Inline Templates)](#ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ãinline-templates) * [ååä»ããã³ãã¬ã¼ã(Named Templates)](#ååä»ããã³ãã¬ã¼ãnamed-templates) * [ãã¡ã¤ã«æ¡å¼µåã®é¢é£ä»ã](#ãã¡ã¤ã«æ¡å¼µåã®é¢é£ä»ã) * [ãªãªã¸ãã«ãã³ãã¬ã¼ãã¨ã³ã¸ã³ã®è¿½å ](#ãªãªã¸ãã«ãã³ãã¬ã¼ãã¨ã³ã¸ã³ã®è¿½å ) * [ãã£ã«ã¿(Filters)](#ãã£ã«ã¿filters) * [ãã«ãã¼(Helpers)](#ãã«ãã¼helpers) * [ã»ãã·ã§ã³ã®ä½¿ç¨](#ã»ãã·ã§ã³ã®ä½¿ç¨) * [åæ¢(Halting)](#åæ¢halting) * [ããã·ã³ã°(Passing)](#ããã·ã³ã°passing) * [å¥ã«ã¼ãã£ã³ã°ã®èªçº](#å¥ã«ã¼ãã£ã³ã°ã®èªçº) * [ããã£ãã¹ãã¼ã¿ã¹ã³ã¼ãããã³ãããã®è¨å®](#ããã£ã¹ãã¼ã¿ã¹ã³ã¼ãããã³ãããã®è¨å®) * [ã¹ããªã¼ãã³ã°ã¬ã¹ãã³ã¹(Streaming Responses)](#ã¹ããªã¼ãã³ã°ã¬ã¹ãã³ã¹streaming-responses) * [ãã®ã³ã°(Logging)](#ãã®ã³ã°logging) * [MIMEã¿ã¤ã(Mime Types)](#mimeã¿ã¤ãmime-types) * [URLã®çæ](#urlã®çæ) * [ãã©ã¦ã¶ãªãã¤ã¬ã¯ã(Browser Redirect)](#ãã©ã¦ã¶ãªãã¤ã¬ã¯ãbrowser-redirect) * [ãã£ãã·ã¥å¶å¾¡(Cache Control)](#ãã£ãã·ã¥å¶å¾¡cache-control) * [ãã¡ã¤ã«ã®éä¿¡](#ãã¡ã¤ã«ã®éä¿¡) * [ãªã¯ã¨ã¹ããªãã¸ã§ã¯ãã¸ã®ã¢ã¯ã»ã¹](#ãªã¯ã¨ã¹ããªãã¸ã§ã¯ãã¸ã®ã¢ã¯ã»ã¹) * [ã¢ã¿ããã¡ã³ã(Attachments)](#ã¢ã¿ããã¡ã³ãattachments) * [æ¥ä»ã¨æå»ã®åãæ±ã](#æ¥ä»ã¨æå»ã®åãæ±ã) * [ãã³ãã¬ã¼ããã¡ã¤ã«ã®æ¢ç´¢](#ãã³ãã¬ã¼ããã¡ã¤ã«ã®æ¢ç´¢) * [ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³(Configuration)](#ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³configuration) * [æ»æé²å¾¡ã«å¯¾ããè¨å®](#æ»æé²å¾¡ã«å¯¾ããè¨å®) * [å©ç¨å¯è½ãªè¨å®](#å©ç¨å¯è½ãªè¨å®) * [ç°å¢è¨å®(Environments)](#ç°å¢è¨å®environments) * [ã¨ã©ã¼ãã³ããªã³ã°(Error Handling)](#ã¨ã©ã¼ãã³ããªã³ã°error-handling) * [Not Found](#not-found) * [ã¨ã©ã¼(Error)](#ã¨ã©ã¼error) * [Rackããã«ã¦ã§ã¢(Rack Middleware)](#rackããã«ã¦ã§ã¢rack-middleware) * [ãã¹ã(Testing)](#ãã¹ãtesting) * [Sinatra::Base - ããã«ã¦ã§ã¢ãã©ã¤ãã©ãªããã³ã¢ã¸ã¥ã©ã¼ã¢ããª](#sinatrabase---ããã«ã¦ã§ã¢ã©ã¤ãã©ãªããã³ã¢ã¸ã¥ã©ã¼ã¢ããª) * [ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã« vs ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«](#ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«-vs-ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«) * [ã¢ã¸ã¥ã©ã¼ã¢ããªã±ã¼ã·ã§ã³ã®æä¾](#ã¢ã¸ã¥ã©ã¼ã¢ããªã±ã¼ã·ã§ã³ã®æä¾) * [config.ruãç¨ããã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã¢ããªã±ã¼ã·ã§ã³ã®ä½¿ç¨](#configruãç¨ããã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã¢ããªã±ã¼ã·ã§ã³ã®ä½¿ç¨) * [config.ruã¯ãã¤ä½¿ãã®ãï¼](#configruã¯ãã¤ä½¿ãã®ã) * [Sinatraã®ããã«ã¦ã§ã¢ã¨ãã¦ã®å©ç¨](#sinatraã®ããã«ã¦ã§ã¢ã¨ãã¦ã®å©ç¨) * [åçãªã¢ããªã±ã¼ã·ã§ã³ã®çæ](#åçãªã¢ããªã±ã¼ã·ã§ã³ã®çæ) * [ã¹ã³ã¼ãã¨ãã¤ã³ãã£ã³ã°(Scopes and Binding)](#ã¹ã³ã¼ãã¨ãã¤ã³ãã£ã³ã°scopes-and-binding) * [ã¢ããªã±ã¼ã·ã§ã³/ã¯ã©ã¹ã®ã¹ã³ã¼ã](#ã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹ã®ã¹ã³ã¼ã) * [ãªã¯ã¨ã¹ã/ã¤ã³ã¹ã¿ã³ã¹ã®ã¹ã³ã¼ã](#ãªã¯ã¨ã¹ãã¤ã³ã¹ã¿ã³ã¹ã®ã¹ã³ã¼ã) * [ããªã²ã¼ãã¹ã³ã¼ã](#ããªã²ã¼ãã¹ã³ã¼ã) * [ã³ãã³ãã©ã¤ã³](#ã³ãã³ãã©ã¤ã³) * [å¿ è¦ç°å¢](#å¿ è¦ç°å¢) * [ææ°éçºç](#ææ°éçºç) * [Bundlerã使ãå ´å](#bundlerã使ãå ´å) * [ç´æ¥çµã¿è¾¼ãå ´å](#ç´æ¥çµã¿è¾¼ãå ´å) * [ã°ãã¼ãã«ç°å¢ã«ã¤ã³ã¹ãã¼ã«ããå ´å](#ã°ãã¼ãã«ç°å¢ã«ã¤ã³ã¹ãã¼ã«ããå ´å) * [ãã¼ã¸ã§ãã³ã°(Versioning)](#ãã¼ã¸ã§ãã³ã°versioning) * [åèæç®](#åèæç®) ## ã«ã¼ãã£ã³ã°(Routes) Sinatraã§ã¯ãã«ã¼ãã£ã³ã°ã¯HTTPã¡ã½ããã¨URLãããã³ã°ãã¿ã¼ã³ããã¢ã«ãªã£ã¦ãã¾ãã ã«ã¼ãã£ã³ã°ã¯ãããã¯ã«çµã³ä»ãããã¦ãã¾ãã ``` ruby get '/' do .. ä½ãè¦ãã .. end post '/' do .. ä½ãçæãã .. end put '/' do .. ä½ãæ´æ°ãã .. end patch '/' do .. ä½ãä¿®æ£ãã .. end delete '/' do .. ä½ãåé¤ãã .. end options '/' do .. ä½ãæºãã .. end link '/' do .. ä½ããªã³ã¯ãå¼µã .. end unlink '/' do .. ä½ãã¢ã³ãªã³ã¯ãã .. end ``` ã«ã¼ãã£ã³ã°ã¯å®ç¾©ãããé çªã«ããããã¾ãã ãªã¯ã¨ã¹ãã«æåã«ãããããã«ã¼ãã£ã³ã°ãå¼ã³åºããã¾ãã ã«ã¼ãã£ã³ã°ã®ãã¿ã¼ã³ã¯ååä»ããã©ã¡ã¼ã¿ãå«ããã¨ãã§ãã `params`ããã·ã¥ã§åå¾ã§ãã¾ãã ``` ruby get '/hello/:name' do # "GET /hello/foo" 㨠"GET /hello/bar" ã«ããã # params['name'] 㯠'foo' ã 'bar' "Hello #{params['name']}!" end ``` ã¾ãããããã¯ãã©ã¡ã¼ã¿ã§ååä»ããã©ã¡ã¼ã¿ã«ã¢ã¯ã»ã¹ãããã¨ãã§ãã¾ãã ``` ruby get '/hello/:name' do |n| # "GET /hello/foo" 㨠"GET /hello/bar" ã«ããã # params['name'] 㯠'foo' ã 'bar' # n ã params['name'] ãä¿æ "Hello #{n}!" end ``` ã«ã¼ãã£ã³ã°ãã¿ã¼ã³ã¯ã¢ã¹ã¿ãªã¹ã¯(ããªãã¡ã¯ã¤ã«ãã«ã¼ã)ãå«ããã¨ãã§ãã `params['splat']` ã§åå¾ã§ãã¾ãã ``` ruby get '/say/*/to/*' do # /say/hello/to/world ã«ããã params['splat'] # => ["hello", "world"] end get '/download/*.*' do # /download/path/to/file.xml ã«ããã params['splat'] # => ["path/to/file", "xml"] end ``` ããã§ããããã¯ãã©ã¡ã¼ã¿ã使ããã¨ãã§ãã¾ãã ``` ruby get '/download/*.*' do |path, ext| [path, ext] # => ["path/to/file", "xml"] end ``` ã«ã¼ãã£ã³ã°ãæ£è¦è¡¨ç¾ã«ãããããããã¨ãã§ãã¾ãã ``` ruby get /\A\/hello\/([\w]+)\z/ do "Hello, #{params['captures'].first}!" end ``` ããã§ãããããã¯ãã©ã¡ã¼ã¿ã使ãã¾ãã ``` ruby get %r{/hello/([\w]+)} do |c| "Hello, #{c}!" end ``` ã«ã¼ãã£ã³ã°ãã¿ã¼ã³ã¯ããªãã·ã§ãã«ãã©ã¡ã¼ã¿ãåããã¨ãã§ãã¾ãã ``` ruby get '/posts.?:format?' do # "GET /posts" 㨠"GET /posts.json", "GET /posts.xml" ã®æ¡å¼µåãªã©ã«ããã end ``` ã¨ããã§ããã£ã¬ã¯ããªãã©ãã¼ãµã«æ»æé²å¾¡è¨å®ãç¡å¹ã«ããªãã¨ï¼ä¸è¨åç §ï¼ã ã«ã¼ãã£ã³ã°ã«ãããããåã«ãªã¯ã¨ã¹ããã¹ãä¿®æ£ãããå¯è½æ§ãããã¾ãã ## æ¡ä»¶(Conditions) ã«ã¼ãã£ã³ã°ã«ã¯ã¦ã¼ã¶ã¨ã¼ã¸ã§ã³ãã®ãããªãã¾ãã¾ãªæ¡ä»¶ãå«ãããã¨ãã§ãã¾ãã ``` ruby get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do "Songbirdã®ãã¼ã¸ã§ã³ #{params['agent'][0]}ã使ã£ã¦ã¾ãã" end get '/foo' do # Songbird以å¤ã®ãã©ã¦ã¶ã«ããã end ``` ã»ãã«`host_name`ã¨`provides`æ¡ä»¶ãå©ç¨å¯è½ã§ãã ``` ruby get '/', :host_name => /^admin\./ do "Adminã¨ãªã¢ã§ããã¢ã¯ã»ã¹ãæå¦ãã¾ã!" end get '/', :provides => 'html' do haml :index end get '/', :provides => ['rss', 'atom', 'xml'] do builder :feed end ``` ç¬èªã®æ¡ä»¶ãå®ç¾©ãããã¨ãç°¡åã«ã§ãã¾ãã ``` ruby set(:probability) { |value| condition { rand <= value } } get '/win_a_car', :probability => 0.1 do "ããªãã®åã¡ã§ã!" end get '/win_a_car' do "æ®å¿µãããªãã®è² ãã§ãã" end ``` è¤æ°ã®å¤ãåãæ¡ä»¶ã«ã¯ãã¢ã¹ã¿ãªã¹ã¯ã使ãã¾ãã ``` ruby set(:auth) do |*roles| # <- ããã§ã¢ã¹ã¿ãªã¹ã¯ã使ã condition do unless logged_in? && roles.any? {|role| current_user.in_role? role } redirect "/login/", 303 end end end get "/my/account/", :auth => [:user, :admin] do "ã¢ã«ã¦ã³ãã®è©³ç´°" end get "/only/admin/", :auth => :admin do "ããã¯ç®¡çè ã ã!" end ``` ## æ»ãå¤(Return Values) ã«ã¼ãã£ã³ã°ãããã¯ã®æ»ãå¤ã¯ãHTTPã¯ã©ã¤ã¢ã³ãã¾ãã¯Rackã¹ã¿ãã¯ã§ã®æ¬¡ã®ããã«ã¦ã§ã¢ã«æ¸¡ãããã¬ã¹ãã³ã¹ããã£ã決å®ãã¾ãã ããã¯å¤§æµã®å ´åãä¸ã®ä¾ã®ããã«æååã§ããããã以å¤ã®å¤ã使ç¨ãããã¨ãã§ãã¾ãã Rackã¬ã¹ãã³ã¹ãRackããã£ãªãã¸ã§ã¯ããHTTPã¹ãã¼ã¿ã¹ã³ã¼ãã®ããããã¨ãã¦å¦¥å½ãªãªãã¸ã§ã¯ãã§ããã°ã©ã®ãããªãªãã¸ã§ã¯ãã§ãè¿ããã¨ãã§ãã¾ãã * 3ã¤ã®è¦ç´ ãå«ãé å: `[ã¹ãã¼ã¿ã¹(Fixnum), ããã(Hash), ã¬ã¹ãã³ã¹ããã£(#eachã«å¿çãã)]` * 2ã¤ã®è¦ç´ ãå«ãé å: `[ã¹ãã¼ã¿ã¹(Fixnum), ã¬ã¹ãã³ã¹ããã£(#eachã«å¿çãã)]` * `#each`ã«å¿çãããªãã¸ã§ã¯ããé常ã¯ãã®ã¾ã¾ä½ãè¿ããªããã ä¸ãããããããã¯ã«æååã渡ãã * ã¹ãã¼ã¿ã¹ã³ã¼ãã表ç¾ããæ´æ°(Fixnum) ããã«ãããä¾ãã°ã¹ããªã¼ãã³ã°ãç°¡åã«å®è£ ãããã¨ãã§ãã¾ãã ``` ruby class Stream def each 100.times { |i| yield "#{i}\n" } end end get('/') { Stream.new } ``` å¾è¿°ãã`stream`ãã«ãã¼ã¡ã½ããã使ã£ã¦ãå®åãã¿ã¼ã³ãæ¸ããã¤ã¤ã¹ããªã¼ãã³ã°ãã¸ãã¯ãã«ã¼ãã£ã³ã°ã«åãè¾¼ããã¨ãã§ãã¾ãã ## ã«ã¹ã¿ã ã«ã¼ãã£ã³ã°ãããã£ã¼(Custom Route Matchers) å è¿°ã®ããã«Sinatraã¯ã«ã¼ãã£ã³ã°ãããã£ã¼ã¨ãã¦ãæååãã¿ã¼ã³ã¨æ£è¦è¡¨ç¾ã使ããã¨ããã«ãã¤ã³ã§ãµãã¼ããã¦ãã¾ãããããããã«çã¾ãããç¬èªã®ãããã£ã¼ãç°¡åã«å®ç¾©ãããã¨ãã§ããã®ã§ãã ``` ruby class AllButPattern Match = Struct.new(:captures) def initialize(except) @except = except @captures = Match.new([]) end def match(str) @captures unless @except === str end end def all_but(pattern) AllButPattern.new(pattern) end get all_but("/index") do # ... end ``` ãã¼ã: ãã®ä¾ã¯ãªã¼ãã¼ã¹ããã¯ã§ããã以ä¸ã®ããã«ãæ¸ããã¨ãã§ãã¾ãã ``` ruby get // do pass if request.path_info == "/index" # ... end ``` ã¾ãã¯ãå¦å®å èªã¿ã使ã£ã¦: ``` ruby get %r{^(?!/index$)} do # ... end ``` ## éçãã¡ã¤ã«(Static Files) éçãã¡ã¤ã«ã¯`./public`ãã£ã¬ã¯ããªããé ä¿¡ããã¾ãã `:public_folder`ãªãã·ã§ã³ãæå®ãããã¨ã§å¥ã®å ´æãæå®ãããã¨ãã§ãã¾ãã ``` ruby set :public_folder, File.dirname(__FILE__) + '/static' ``` ãã¼ã: ãã®éçãã¡ã¤ã«ç¨ã®ãã£ã¬ã¯ããªåã¯URLä¸ã«å«ã¾ãã¾ããã ä¾ãã°ã`./public/css/style.css`ã¯`http://example.com/css/style.css`ã§ã¢ã¯ã»ã¹ã§ãã¾ãã `Cache-Control`ã®è¨å®ããããã¼ã¸è¿½å ããã«ã¯`:static_cache_control`ã®è¨å®(ä¸è¨åç §)ãå ãã¦ãã ããã ## ãã¥ã¼ / ãã³ãã¬ã¼ã(Views / Templates) åãã³ãã¬ã¼ãè¨èªã¯ããèªèº«ã®ã¬ã³ããªã³ã°ã¡ã½ãããéãã¦å±éããã¾ãããããã®ã¡ã½ããã¯åã«æååãè¿ãã¾ãã ``` ruby get '/' do erb :index end ``` ããã¯ã`views/index.erb`ãã¬ã³ããªã³ã°ãã¾ãã ãã³ãã¬ã¼ãåã渡ã代ããã«ãç´æ¥ãã®ãã³ãã¬ã¼ãã®ä¸èº«ã渡ããã¨ãã§ãã¾ãã ``` ruby get '/' do code = "<%= Time.now %>" erb code end ``` ãã³ãã¬ã¼ãã®ã¬ã¤ã¢ã¦ãã¯ç¬¬ï¼å¼æ°ã®ããã·ã¥å½¢å¼ã®ãªãã·ã§ã³ããã¨ã«è¡¨ç¤ºããã¾ãã ``` ruby get '/' do erb :index, :layout => :post end ``` ããã¯ã`views/post.erb`å ã«åãè¾¼ã¾ãã`views/index.erb`ãã¬ã³ããªã³ã°ãã¾ãï¼ããã©ã«ãã¯`views/layout.erb`ãããã°ããã«ãªãã¾ãï¼ã Sinatraãç解ã§ããªããªãã·ã§ã³ã¯ããã³ãã¬ã¼ãã¨ã³ã¸ã³ã«æ¸¡ããããã¨ã«ãªãã¾ãã ``` ruby get '/' do haml :index, :format => :html5 end ``` ãã³ãã¬ã¼ãè¨èªãã¨ã«ãªãã·ã§ã³ãã»ãããããã¨ãã§ãã¾ãã ``` ruby set :haml, :format => :html5 get '/' do haml :index end ``` ã¬ã³ããªã³ã°ã¡ã½ããã«æ¸¡ããããªãã·ã§ã³ã¯`set`ã§è¨å®ããããªãã·ã§ã³ãä¸æ¸ããã¾ãã å©ç¨å¯è½ãªãªãã·ã§ã³: <dl> <dt>locals</dt> <dd> ããã¥ã¡ã³ãã«æ¸¡ããããã¼ã«ã«ã®ãªã¹ãããã¼ã·ã£ã«ã«ä¾¿å©ã ä¾: <tt>erb "<%= foo %>", :locals => {:foo => "bar"}</tt> </dd> <dt>default_encoding</dt> <dd> æåã¨ã³ã³ã¼ãã£ã³ã°ï¼ä¸ç¢ºããªå ´åã«ä½¿ç¨ãããï¼ãããã©ã«ãã¯ã<tt>settings.default_encoding</tt>ã </dd> <dt>views</dt> <dd> ãã³ãã¬ã¼ããèªã¿åºããã¥ã¼ã®ãã£ã¬ã¯ããªãããã©ã«ãã¯ã<tt>settings.views</tt>ã </dd> <dt>layout</dt> <dd> ã¬ã¤ã¢ã¦ãã使ããã®æå®(<tt>true</tt> ã¾ã㯠<tt>false</tt>)ãå¤ãã·ã³ãã«ã®å ´åã¯ã使ç¨ãããã³ãã¬ã¼ããæå®ããããä¾: <tt>erb :index, :layout => !request.xhr?</tt> </dd> <dt>content_type</dt> <dd> ãã³ãã¬ã¼ããçæããContent-Typeãããã©ã«ãã¯ãã³ãã¬ã¼ãè¨èªãã¨ã«ç°ãªãã </dd> <dt>scope</dt> <dd> ãã³ãã¬ã¼ããã¬ã³ããªã³ã°ããã¨ãã®ã¹ã³ã¼ããããã©ã«ãã¯ãã¢ããªã±ã¼ã·ã§ã³ã®ã¤ã³ã¹ã¿ã³ã¹ããããå¤æ´ããå ´åãã¤ã³ã¹ã¿ã³ã¹å¤æ°ããã³ãã«ãã¼ã¡ã½ãããå©ç¨ã§ããªããªãã </dd> <dt>layout_engine</dt> <dd> ã¬ã¤ã¢ã¦ããã¬ã³ããªã³ã°ããããã«ä½¿ç¨ãããã³ãã¬ã¼ãã¨ã³ã¸ã³ãã¬ã¤ã¢ã¦ãããµãã¼ãããªãè¨èªã§æç¨ãããã©ã«ãã¯ãã³ãã¬ã¼ãã«ä½¿ãããã¨ã³ã¸ã³ãä¾: <tt>set :rdoc, :layout_engine => :erb</tt> </dd> <dt>layout_options</dt> <dd> ã¬ã¤ã¢ã¦ããã¬ã³ããªã³ã°ããã¨ãã ãã«ä½¿ãç¹å¥ãªãªãã·ã§ã³ãä¾: <tt>set :rdoc, :layout_options => { :views => 'views/layouts' }</tt> </dd> </dl> ãã³ãã¬ã¼ãã¯`./views`ãã£ã¬ã¯ããªä¸ã«é ç½®ããã¦ãã¾ãã ä»ã®ãã£ã¬ã¯ããªã使ç¨ããå ´åã®ä¾: ``` ruby set :views, settings.root + '/templates' ``` ãã³ãã¬ã¼ãã¯ã·ã³ãã«ã使ç¨ãã¦åç §ããããã¨ãè¦ãã¦ããã¦ä¸ããã ãµããã£ã¬ã¯ããªã§ããã®å ´åã¯`:'subdir/template'`ã®ããã«ãã¾ãã ã¬ã³ããªã³ã°ã¡ã½ããã¯æååã渡ãããã¨ãããããã®ã¾ã¾æååã¨ãã¦åºåããã®ã§ãã·ã³ãã«ã使ã£ã¦ãã ããã ### ãªãã©ã«ãã³ãã¬ã¼ã(Literal Templates) ``` ruby get '/' do haml '%div.title Hello World' end ``` ããã¯ãã®ãã³ãã¬ã¼ãæååãã¬ã³ããªã³ã°ãã¾ãã ### å©ç¨å¯è½ãªãã³ãã¬ã¼ãè¨èª ããã¤ãã®è¨èªã«ã¯è¤æ°ã®å®è£ ãããã¾ãã使ç¨ããï¼ããã¦ã¹ã¬ããã»ã¼ãã«ããï¼å®è£ ãæå®ããã«ã¯ããããæåã«requireãã¦ãã ããã ``` ruby require 'rdiscount' # ã¾ã㯠require 'bluecloth' get('/') { markdown :index } ``` #### Haml ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://haml.info/" title="haml">haml</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.haml</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>haml :index, :format => :html5</tt></td> </tr> </table> #### Erb ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td> <a href="http://www.kuwata-lab.com/erubis/" title="erubis">erubis</a> ã¾ã㯠erb (Rubyã«å梱) </td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.erb</tt>, <tt>.rhtml</tt> or <tt>.erubis</tt> (Erubisã ã)</td> </tr> <tr> <td>ä¾</td> <td><tt>erb :index</tt></td> </tr> </table> #### Builder ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td> <a href="https://github.com/jimweirich/builder" title="builder">builder</a> </td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.builder</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>builder { |xml| xml.em "hi" }</tt></td> </tr> </table> ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ãç¨ã«ãããã¯ãåããã¨ãã§ãã¾ãï¼ä¾ãåç §ï¼ã #### Nokogiri ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://nokogiri.org/" title="nokogiri">nokogiri</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.nokogiri</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>nokogiri { |xml| xml.em "hi" }</tt></td> </tr> </table> ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ãç¨ã«ãããã¯ãåããã¨ãã§ãã¾ãï¼ä¾ãåç §ï¼ã #### Sass ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://sass-lang.com/" title="sass">sass</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.sass</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>sass :stylesheet, :style => :expanded</tt></td> </tr> </table> #### Scss ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://sass-lang.com/" title="sass">sass</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.scss</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>scss :stylesheet, :style => :expanded</tt></td> </tr> </table> #### Less ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://www.lesscss.org/" title="less">less</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.less</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>less :stylesheet</tt></td> </tr> </table> #### Liquid ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://www.liquidmarkup.org/" title="liquid">liquid</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.liquid</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>liquid :index, :locals => { :key => 'value' }</tt></td> </tr> </table> Liquidãã³ãã¬ã¼ãããRubyã®ã¡ã½ãã(`yield`ãé¤ã)ãå¼ã³åºããã¨ãã§ããªããããã»ã¼å ¨ã¦ã®å ´åã«localsãæå®ããå¿ è¦ãããã§ãããã #### Markdown ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td> 次ã®ä½ãã: <a href="https://github.com/rtomayko/rdiscount" title="RDiscount">RDiscount</a>, <a href="https://github.com/vmg/redcarpet" title="RedCarpet">RedCarpet</a>, <a href="http://deveiate.org/projects/BlueCloth" title="BlueCloth">BlueCloth</a>, <a href="http://kramdown.gettalong.org/" title="kramdown">kramdown</a>, <a href="https://github.com/bhollis/maruku" title="maruku">maruku</a> </td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.markdown</tt>, <tt>.mkd</tt> and <tt>.md</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>markdown :index, :layout_engine => :erb</tt></td> </tr> </table> Markdownããã¡ã½ãããå¼ã³åºããã¨ããlocalsã«å¤æ°ã渡ããã¨ãã§ãã¾ããã ãããããä»ã®ã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨ã®çµã¿åããã§ä½¿ãã®ãæ®éã§ãã ``` ruby erb :overview, :locals => { :text => markdown(:introduction) } ``` ãã¼ã: ä»ã®ãã³ãã¬ã¼ãå ã§`markdown`ã¡ã½ãããå¼ã³åºãã¾ãã ``` ruby %h1 Hello From Haml! %p= markdown(:greetings) ``` Markdownããã¯Rubyãå¼ã¶ãã¨ãã§ããªãã®ã§ãMarkdownã§æ¸ãããã¬ã¤ã¢ã¦ãã使ããã¨ã¯ã§ãã¾ãããããããªããã`:layout_engine`ãªãã·ã§ã³ã渡ããã¨ã§ãã³ãã¬ã¼ãã®ãã®ã¨ã¯ç°ãªãã¬ã³ããªã³ã°ã¨ã³ã¸ã³ãã¬ã¤ã¢ã¦ãã®ããã«ä½¿ããã¨ãã§ãã¾ãã #### Textile ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://redcloth.org/" title="RedCloth">RedCloth</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.textile</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>textile :index, :layout_engine => :erb</tt></td> </tr> </table> Textileããã¡ã½ãããå¼ã³åºããã¨ããlocalsã«å¤æ°ã渡ããã¨ãã§ãã¾ããã ãããããä»ã®ã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨ã®çµã¿åããã§ä½¿ãã®ãæ®éã§ãã ``` ruby erb :overview, :locals => { :text => textile(:introduction) } ``` ãã¼ã: ä»ã®ãã³ãã¬ã¼ãå ã§`textile`ã¡ã½ãããå¼ã³åºãã¾ãã ``` ruby %h1 Hello From Haml! %p= textile(:greetings) ``` Texttileããã¯Rubyãå¼ã¶ãã¨ãã§ããªãã®ã§ãTextileã§æ¸ãããã¬ã¤ã¢ã¦ãã使ããã¨ã¯ã§ãã¾ãããããããªããã`:layout_engine`ãªãã·ã§ã³ã渡ããã¨ã§ãã³ãã¬ã¼ãã®ãã®ã¨ã¯ç°ãªãã¬ã³ããªã³ã°ã¨ã³ã¸ã³ãã¬ã¤ã¢ã¦ãã®ããã«ä½¿ããã¨ãã§ãã¾ãã #### RDoc ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://rdoc.sourceforge.net/" title="RDoc">RDoc</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.rdoc</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>rdoc :README, :layout_engine => :erb</tt></td> </tr> </table> RDocããã¡ã½ãããå¼ã³åºããã¨ããlocalsã«å¤æ°ã渡ããã¨ãã§ãã¾ããã ãããããä»ã®ã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨ã®çµã¿åããã§ä½¿ãã®ãæ®éã§ãã ``` ruby erb :overview, :locals => { :text => rdoc(:introduction) } ``` ãã¼ã: ä»ã®ãã³ãã¬ã¼ãå ã§`rdoc`ã¡ã½ãããå¼ã³åºãã¾ãã ``` ruby %h1 Hello From Haml! %p= rdoc(:greetings) ``` RDocããã¯Rubyãå¼ã¶ãã¨ãã§ããªãã®ã§ãRDocã§æ¸ãããã¬ã¤ã¢ã¦ãã使ããã¨ã¯ã§ãã¾ãããããããªããã`:layout_engine`ãªãã·ã§ã³ã渡ããã¨ã§ãã³ãã¬ã¼ãã®ãã®ã¨ã¯ç°ãªãã¬ã³ããªã³ã°ã¨ã³ã¸ã³ãã¬ã¤ã¢ã¦ãã®ããã«ä½¿ããã¨ãã§ãã¾ãã #### AsciiDoc ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://asciidoctor.org/" title="Asciidoctor">Asciidoctor</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.asciidoc</tt>, <tt>.adoc</tt> and <tt>.ad</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>asciidoc :README, :layout_engine => :erb</tt></td> </tr> </table> AsciiDocãã³ãã¬ã¼ãããRubyã®ã¡ã½ãããç´æ¥å¼ã³åºããã¨ãã§ããªããããã»ã¼å ¨ã¦ã®å ´åã«localsãæå®ããå¿ è¦ãããã§ãããã #### Radius ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/jlong/radius" title="Radius">Radius</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.radius</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>radius :index, :locals => { :key => 'value' }</tt></td> </tr> </table> Radiusãã³ãã¬ã¼ãããRubyã®ã¡ã½ãããç´æ¥å¼ã³åºããã¨ãã§ããªããããã»ã¼å ¨ã¦ã®å ´åã«localsãæå®ããå¿ è¦ãããã§ãããã #### Markaby ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://markaby.github.com/" title="Markaby">Markaby</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.mab</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>markaby { h1 "Welcome!" }</tt></td> </tr> </table> ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ãç¨ã«ãããã¯ãåããã¨ãã§ãã¾ãï¼ä¾ãåç §ï¼ã #### RABL ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/nesquena/rabl" title="Rabl">Rabl</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.rabl</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>rabl :index</tt></td> </tr> </table> #### Slim ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="http://slim-lang.com/" title="Slim Lang">Slim Lang</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.slim</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>slim :index</tt></td> </tr> </table> #### Creole ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/minad/creole" title="Creole">Creole</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.creole</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>creole :wiki, :layout_engine => :erb</tt></td> </tr> </table> Creoleããã¡ã½ãããå¼ã³åºããã¨ããlocalsã«å¤æ°ã渡ããã¨ãã§ãã¾ããã ãããããä»ã®ã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨ã®çµã¿åããã§ä½¿ãã®ãæ®éã§ãã ``` ruby erb :overview, :locals => { :text => creole(:introduction) } ``` ãã¼ã: ä»ã®ãã³ãã¬ã¼ãå ã§`creole`ã¡ã½ãããå¼ã³åºãã¾ãã ``` ruby %h1 Hello From Haml! %p= creole(:greetings) ``` Creoleããã¯Rubyãå¼ã¶ãã¨ãã§ããªãã®ã§ãCreoleã§æ¸ãããã¬ã¤ã¢ã¦ãã使ããã¨ã¯ã§ãã¾ãããããããªããã`:layout_engine`ãªãã·ã§ã³ã渡ããã¨ã§ãã³ãã¬ã¼ãã®ãã®ã¨ã¯ç°ãªãã¬ã³ããªã³ã°ã¨ã³ã¸ã³ãã¬ã¤ã¢ã¦ãã®ããã«ä½¿ããã¨ãã§ãã¾ãã #### MediaWiki ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/nricciar/wikicloth" title="WikiCloth">WikiCloth</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.mediawiki</tt> ããã³ <tt>.mw</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>mediawiki :wiki, :layout_engine => :erb</tt></td> </tr> </table> MediaWikiã®ãã³ãã¬ã¼ãã¯ç´æ¥ã¡ã½ããããå¼ã³åºãããããã¼ã«ã«å¤æ°ãéããã¨ã¯ã§ãã¾ãããããããã«ãé常ã¯å¥ã®ã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨çµã¿åããã¦å©ç¨ãã¾ãã ```ruby erb :overview, :locals => { :text => mediawiki(:introduction) } ``` ãã¼ã: ä»ã®ãã³ãã¬ã¼ãããé¨åçã«`mediawiki`ã¡ã½ãããå¼ã³åºããã¨ãå¯è½ã§ãã #### CoffeeScript ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td> <a href="https://github.com/josh/ruby-coffee-script" title="Ruby CoffeeScript"> CoffeeScript </a> ããã³ <a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS"> JavaScriptã®èµ·åæ¹æ³ </a> </td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.coffee</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>coffee :index</tt></td> </tr> </table> #### Stylus ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td> <a href="https://github.com/lucasmazza/ruby-stylus" title="Ruby Stylus"> Stylus </a> ããã³ <a href="https://github.com/sstephenson/execjs/blob/master/README.md#readme" title="ExecJS"> JavaScriptã®èµ·åæ¹æ³ </a> </td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.styl</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>stylus :index</tt></td> </tr> </table> Stylusãã³ãã¬ã¼ãã使ããããã«ããåã«ãã¾ã`stylus`ã¨`stylus/tilt`ãèªã¿è¾¼ãå¿ è¦ãããã¾ãã ``` ruby require 'sinatra' require 'stylus' require 'stylus/tilt' get '/' do stylus :example end ``` #### Yajl ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/brianmario/yajl-ruby" title="yajl-ruby">yajl-ruby</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.yajl</tt></td> </tr> <tr> <td>ä¾</td> <td> <tt> yajl :index, :locals => { :key => 'qux' }, :callback => 'present', :variable => 'resource' </tt> </td> </tr> </table> ãã³ãã¬ã¼ãã®ã½ã¼ã¹ã¯Rubyã®æååã¨ãã¦è©ä¾¡ããããã®çµæã®JSONå¤æ°ã¯`#to_json`ã使ã£ã¦å¤æããã¾ãã ``` ruby json = { :foo => 'bar' } json[:baz] = key ``` `:callback`ããã³`:variable`ãªãã·ã§ã³ã¯ãã¬ã³ããªã³ã°ããããªãã¸ã§ã¯ããè£ é£¾ããããã«ä½¿ããã¨ãã§ãã¾ãã ``` ruby var resource = {"foo":"bar","baz":"qux"}; present(resource); ``` #### WLang ãã³ãã¬ã¼ã <table> <tr> <td>ä¾å</td> <td><a href="https://github.com/blambeau/wlang/" title="wlang">wlang</a></td> </tr> <tr> <td>ãã¡ã¤ã«æ¡å¼µå</td> <td><tt>.wlang</tt></td> </tr> <tr> <td>ä¾</td> <td><tt>wlang :index, :locals => { :key => 'value' }</tt></td> </tr> </table> WLangå ã§ã®Rubyã¡ã½ããã®å¼ã³åºãã¯ä¸è¬çã§ã¯ãªãã®ã§ãã»ã¨ãã©ã®å ´åã«localsãæå®ããå¿ è¦ãããã§ããããããããªãããWLangã§æ¸ãããã¬ã¤ã¢ã¦ãã¯`yield`ããµãã¼ããã¦ãã¾ãã ### ãã³ãã¬ã¼ãå ã§ã®å¤æ°ã¸ã®ã¢ã¯ã»ã¹ ãã³ãã¬ã¼ãã¯ã«ã¼ãã£ã³ã°ãã³ãã©ã¨åãã³ã³ããã¹ãã®ä¸ã§è©ä¾¡ããã¾ããã«ã¼ãã£ã³ã°ãã³ãã©ã§ã»ãããããã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯ãã³ãã¬ã¼ãå ã§ç´æ¥ä½¿ããã¨ãã§ãã¾ãã ``` ruby get '/:id' do @foo = Foo.find(params['id']) haml '%h1= @foo.name' end ``` ã¾ãããã¼ã«ã«å¤æ°ã®ããã·ã¥ã§æ示çã«æå®ãããã¨ãã§ãã¾ãã ``` ruby get '/:id' do foo = Foo.find(params['id']) haml '%h1= bar.name', :locals => { :bar => foo } end ``` ãã®ããæ¹ã¯ä»ã®ãã³ãã¬ã¼ãå ã§é¨åãã³ãã¬ã¼ãã¨ãã¦è¡¨ç¤ºããæã«å ¸åçã«ä½¿ç¨ããã¾ãã ### `yield`ãä¼´ããã³ãã¬ã¼ãã¨ãã¹ãããã¬ã¤ã¢ã¦ã ã¬ã¤ã¢ã¦ãã¯é常ã`yield`ãå¼ã¶åãªããã³ãã¬ã¼ãã«éãã¾ããã ãã®ãããªãã³ãã¬ã¼ãã¯ãæ¢ã«èª¬æãã`:template`ãªãã·ã§ã³ãéãã¦ä½¿ãããããã¾ãã¯æ¬¡ã®ãããªãããã¯ãä¼´ã£ã¦ã¬ã³ããªã³ã°ããã¾ãã ``` ruby erb :post, :layout => false do erb :index end ``` ãã®ã³ã¼ãã¯ã`erb :index, :layout => :post`ã¨ã»ã¼ç価ã§ãã ã¬ã³ããªã³ã°ã¡ã½ããã«ãããã¯ã渡ãã¹ã¿ã¤ã«ã¯ããã¹ãããã¬ã¤ã¢ã¦ããä½ãããã«æãå½¹ç«ã¡ã¾ãã ``` ruby erb :main_layout, :layout => false do erb :admin_layout do erb :user end end ``` ããã¯ã¾ã次ã®ããçãã³ã¼ãã§ãéæã§ãã¾ãã ``` ruby erb :admin_layout, :layout => :main_layout do erb :user end ``` ç¾å¨ã次ã®ã¬ã³ããªã³ã°ã¡ã½ããããããã¯ãåãã¾ã: `erb`, `haml`, `liquid`, `slim `, `wlang`ã ã¾ãæ±ç¨ã®`render`ã¡ã½ããããããã¯ãåãã¾ãã ### ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ã(Inline Templates) ãã³ãã¬ã¼ãã¯ã½ã¼ã¹ãã¡ã¤ã«ã®æå¾ã§å®ç¾©ãããã¨ãã§ãã¾ãã ``` ruby require 'sinatra' get '/' do haml :index end __END__ @@ layout %html = yield @@ index %div.title Hello world!!!!! ``` ãã¼ã: Sinatraãrequireããã½ã¼ã¹ãã¡ã¤ã«å ã§å®ç¾©ãããã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ãã¯èªåçã«èªã¿è¾¼ã¾ãã¾ããä»ã®ã½ã¼ã¹ãã¡ã¤ã«å ã«ã¤ã³ã©ã¤ã³ãã³ãã¬ã¼ããããå ´åã«ã¯`enable :inline_templates`ãæ示çã«å¼ãã§ãã ããã ### ååä»ããã³ãã¬ã¼ã(Named Templates) ãã³ãã¬ã¼ãã¯ãããã¬ãã«ã®`template`ã¡ã½ããã§å®ç¾©ãããã¨ãã§ãã¾ãã ``` ruby template :layout do "%html\n =yield\n" end template :index do '%div.title Hello World!' end get '/' do haml :index end ``` ãlayoutãã¨ãããã³ãã¬ã¼ããåå¨ããå ´åããã®ãã³ãã¬ã¼ããã¡ã¤ã«ã¯ä»ã®ãã³ãã¬ã¼ããã¬ã³ããªã³ã°ããã度ã«ä½¿ç¨ããã¾ãã`:layout => false`ã§åå¥ã«ãã¾ãã¯`set :haml, :layout => false`ã§ããã©ã«ãã¨ãã¦ãã¬ã¤ã¢ã¦ããç¡å¹ã«ãããã¨ãã§ãã¾ãã ``` ruby get '/' do haml :index, :layout => !request.xhr? end ``` ### ãã¡ã¤ã«æ¡å¼µåã®é¢é£ä»ã ä»»æã®ãã³ãã¬ã¼ãã¨ã³ã¸ã³ã«ãã¡ã¤ã«æ¡å¼µåãé¢é£ä»ããå ´åã¯ã`Tilt.register`ã使ãã¾ããä¾ãã°ãTextileãã³ãã¬ã¼ãã«`tt`ã¨ãããã¡ã¤ã«æ¡å¼µåã使ãããå ´åã¯ã以ä¸ã®ããã«ãã¾ãã ``` ruby Tilt.register :tt, Tilt[:textile] ``` ### ãªãªã¸ãã«ãã³ãã¬ã¼ãã¨ã³ã¸ã³ã®è¿½å ã¾ããTiltã§ãã®ã¨ã³ã¸ã³ãç»é²ãã次ã«ã¬ã³ããªã³ã°ã¡ã½ãããä½ãã¾ãã ``` ruby Tilt.register :myat, MyAwesomeTemplateEngine helpers do def myat(*args) render(:myat, *args) end end get '/' do myat :index end ``` ããã¯ã`./views/index.myat`ãã¬ã³ããªã³ã°ãã¾ããTiltã«ã¤ãã¦ã®è©³ç´°ã¯ãhttps://github.com/rtomayko/tilt ãåç §ãã¦ãã ããã ## ãã£ã«ã¿(Filters) beforeãã£ã«ã¿ã¯ããªã¯ã¨ã¹ãã®ã«ã¼ãã£ã³ã°ã¨åãã³ã³ããã¹ãã§åãªã¯ã¨ã¹ãã®åã«è©ä¾¡ãããããã«ãã£ã¦ãªã¯ã¨ã¹ãã¨ã¬ã¹ãã³ã¹ãå¤æ´å¯è½ã«ãã¾ãããã£ã«ã¿å ã§ã»ãããããã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯ã«ã¼ãã£ã³ã°ã¨ãã³ãã¬ã¼ãããã¢ã¯ã»ã¹ãããã¨ãã§ãã¾ãã ``` ruby before do @note = 'Hi!' request.path_info = '/foo/bar/baz' end get '/foo/*' do @note #=> 'Hi!' params['splat'] #=> 'bar/baz' end ``` afterãã£ã«ã¿ã¯ããªã¯ã¨ã¹ãã®ã«ã¼ãã£ã³ã°ã¨åãã³ã³ããã¹ãã§åãªã¯ã¨ã¹ãã®å¾ã«è©ä¾¡ãããããã«ãã£ã¦ããããªã¯ã¨ã¹ãã¨ã¬ã¹ãã³ã¹ãå¤æ´å¯è½ã«ãã¾ããbeforeãã£ã«ã¿ã¨ã«ã¼ãã£ã³ã°å ã§ã»ãããããã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯afterãã£ã«ã¿ããã¢ã¯ã»ã¹ãããã¨ãã§ãã¾ãã ``` ruby after do puts response.status end ``` ãã¼ã: `body`ã¡ã½ããã使ããã«ã«ã¼ãã£ã³ã°ããæååãè¿ãã ãã®å ´åããã®å 容ã¯afterãã£ã«ã¿ã§ã¾ã å©ç¨ã§ããããã®å¾ã«çæããããã¨ã«ãªãã¾ãã ãã£ã«ã¿ã«ã¯ãªãã·ã§ã³ã¨ãã¦ãã¿ã¼ã³ã渡ããã¨ãã§ãããã®å ´åã¯ãªã¯ã¨ã¹ãã®ãã¹ããã¿ã¼ã³ã«ãããããå ´åã«ã®ã¿ãã£ã«ã¿ãè©ä¾¡ãããããã«ãªãã¾ãã ``` ruby before '/protected/*' do authenticate! end after '/create/:slug' do |slug| session[:last_slug] = slug end ``` ã«ã¼ãã£ã³ã°åæ§ããã£ã«ã¿ãã¾ãæ¡ä»¶ãåããã¨ãã§ãã¾ãã ``` ruby before :agent => /Songbird/ do # ... end after '/blog/*', :host_name => 'example.com' do # ... end ``` ## ãã«ãã¼(Helpers) ãããã¬ãã«ã®`helpers`ã¡ã½ããã使ç¨ãã¦ã«ã¼ãã£ã³ã°ãã³ãã©ããã³ãã¬ã¼ãã§ä½¿ããã«ãã¼ã¡ã½ãããå®ç¾©ã§ãã¾ãã ``` ruby helpers do def bar(name) "#{name}bar" end end get '/:name' do bar(params['name']) end ``` ãããã¯ããã«ãã¼ã¡ã½ãããã¢ã¸ã¥ã¼ã«å ã§åå¥ã«å®ç¾©ãããã¨ãã§ãã¾ãã ``` ruby module FooUtils def foo(name) "#{name}foo" end end module BarUtils def bar(name) "#{name}bar" end end helpers FooUtils, BarUtils ``` ãã®å¹æã¯ãã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹ã«ã¢ã¸ã¥ã¼ã«ãã¤ã³ã¯ã«ã¼ãããã®ã¨åãã§ãã ### ã»ãã·ã§ã³ã®ä½¿ç¨ ã»ãã·ã§ã³ã¯ãªã¯ã¨ã¹ãéã§ã®ç¶æ ç¶æã®ããã«ä½¿ç¨ããã¾ãããã®èµ·åã«ãããã¦ã¼ã¶ã»ãã·ã§ã³ãã¨ã«ä¸ã¤ã®ã»ãã·ã§ã³ããã·ã¥ãä¸ãããã¾ãã ``` ruby enable :sessions get '/' do "value = " << session[:value].inspect end get '/:value' do session[:value] = params['value'] end ``` ãã¼ã: `enable :sessions`ã¯å®éã«ã¯ãã¹ã¦ã®ãã¼ã¿ãã¯ããã¼ã«ä¿æãã¾ããããã¯å¿ ãããæå¾ éãã®ãã®ã«ãªããªãããããã¾ããï¼ä¾ãã°ã大éã®ãã¼ã¿ãä¿æãããã¨ã§ãã©ãã£ãã¯ãå¢å¤§ãããªã©ï¼ãRackã»ãã·ã§ã³ããã«ã¦ã§ã¢ã®å©ç¨ãå¯è½ã§ããããã®å ´åã¯`enable :sessions`ãå¼ã°ãã«ãé¸æããããã«ã¦ã§ã¢ãä»ã®ããã«ã¦ã§ã¢ã®ã¨ãã¨åãããã«ãã¦åãè¾¼ãã§ãã ããã ``` ruby use Rack::Session::Pool, :expire_after => 2592000 get '/' do "value = " << session[:value].inspect end get '/:value' do session[:value] = params['value'] end ``` ã»ãã¥ãªãã£åä¸ã®ãããã¯ããã¼å ã®ã»ãã·ã§ã³ãã¼ã¿ã¯ã»ãã·ã§ã³ç§å¯éµ(session secret)ã§ç½²åããã¾ããSinatraã«ããã©ã³ãã ãªç§å¯éµãåå¥ã«çæããã¾ãããããããã®ç§å¯éµã¯ã¢ããªã±ã¼ã·ã§ã³ã®ç«ã¡ä¸ããã¨ã«å¤ãã£ã¦ãã¾ãã®ã§ããã¹ã¦ã®ã¢ããªã±ã¼ã·ã§ã³ã®ã¤ã³ã¹ã¿ã³ã¹ã§å ±æã§ããç§å¯éµãã»ããããããªãããããã¾ããã ``` ruby set :session_secret, 'super secret' ``` æ´ã«ãè¨å®å¤æ´ããããå ´åã¯ã`sessions`ã®è¨å®ã«ããã¦ãªãã·ã§ã³ããã·ã¥ãä¿æãããã¨ãã§ãã¾ãã ``` ruby set :sessions, :domain => 'foo.com' ``` foo.comã®ãµããã¡ã¤ã³ä¸ã®ã¢ããªéã§ã»ãã·ã§ã³ãå ±æåãããã¨ãã¯ã代ããã«ãã¡ã¤ã³ã®åã« *.* ãä»ãã¾ãã ``` ruby set :sessions, :domain => '.foo.com' ``` ### åæ¢(Halting) ãã£ã«ã¿ã¾ãã¯ã«ã¼ãã£ã³ã°å ã§ç´ã¡ã«ãªã¯ã¨ã¹ããæ¢ããå ´å ``` ruby halt ``` ãã®éãã¹ãã¼ã¿ã¹ãæå®ãããã¨ãã§ãã¾ãã ``` ruby halt 410 ``` bodyé¨ãæå®ãããã¨ãã ``` ruby halt 'ããã«bodyãæ¸ã' ``` ã¹ãã¼ã¿ã¹ã¨bodyé¨ãæå®ãããã¨ãã ``` ruby halt 401, 'ç«ã¡å»ã!' ``` ããããä»ãããã¨ãã§ãã¾ãã ``` ruby halt 402, {'Content-Type' => 'text/plain'}, 'ãªãã³ã¸' ``` ãã¡ããããã³ãã¬ã¼ãã`halt`ã«çµã³ã¤ãããã¨ãå¯è½ã§ãã ``` ruby halt erb(:error) ``` ### ããã·ã³ã°(Passing) ã«ã¼ãã£ã³ã°ã¯`pass`ã使ã£ã¦æ¬¡ã®ã«ã¼ãã£ã³ã°ã«é£ã°ããã¨ãã§ãã¾ãã ``` ruby get '/guess/:who' do pass unless params['who'] == 'Frank' "è¦ã¤ãã£ã¡ãã£ã!" end get '/guess/*' do "ã¯ããã§ã!" end ``` ã«ã¼ãã£ã³ã°ãããã¯ããããã«æãåºãã次ã«ãããããã«ã¼ãã£ã³ã°ãå®è¡ãã¾ãããããããã«ã¼ãã£ã³ã°ãè¦å½ãããªãå ´åã¯404ãè¿ããã¾ãã ### å¥ã«ã¼ãã£ã³ã°ã®èªçº `pass`ã使ã£ã¦ã«ã¼ãã£ã³ã°ãé£ã°ãã®ã§ã¯ãªããä»ã®ã«ã¼ãã£ã³ã°ãå¼ãã çµæãå¾ããã¨ããã¨ããããã¾ãããããå®ç¾ããã«ã¯`call`ã使ãã°ããã§ãã ``` ruby get '/foo' do status, headers, body = call env.merge("PATH_INFO" => '/bar') [status, headers, body.map(&:upcase)] end get '/bar' do "bar" end ``` ãã¼ã: å ã®ä¾ã«ããã¦ããã¹ãã楽ã«ãããã©ã¼ãã³ã¹ãæ¹åããã«ã¯ã`"bar"`ãåã«ãã«ãã¼ã«ç§»ãã`/foo`ããã³`/bar`ãã使ããããã«ããã®ãããã§ãã ãªã¯ã¨ã¹ããããã®è¤è£½ç©ã§ãªãåãã¢ããªã±ã¼ã·ã§ã³ã®ã¤ã³ã¹ã¿ã³ã¹ã«éãããããã«ãããã¨ãã¯ã`call`ã«ä»£ãã¦`call!`ã使ã£ã¦ãã ããã `call`ã«ã¤ãã¦ã®è©³ç´°ã¯Rackã®ä»æ§æ¸ãåç §ãã¦ãã ããã ### ããã£ãã¹ãã¼ã¿ã¹ã³ã¼ãããã³ãããã®è¨å® ã¹ãã¼ã¿ã¹ã³ã¼ãããã³ã¬ã¹ãã³ã¹ããã£ããã«ã¼ãã£ã³ã°ãããã¯ã®æ»ãå¤ã«ã»ãããããã¨ãå¯è½ã§ãããããã¯æ¨å¥¨ããã¦ãã¾ããããããããã±ã¼ã¹ã§ã¯å®è¡ããã¼ã®ä»»æã®ã¿ã¤ãã³ã°ã§ããã£ãã»ããããããªãããããã¾ããã`body`ãã«ãã¼ã¡ã½ããã使ãã°ãããã§ãã¾ããããããã¨ããã以éãããã£ã«ã¢ã¯ã»ã¹ããããã«ãã®ã¡ã½ããã使ããã¨ãã§ããããã«ãªãã¾ãã ``` ruby get '/foo' do body "bar" end after do puts body end ``` ã¾ãã`body`ã«ã¯ãããã¯ã渡ããã¨ãã§ããããã¯Rackãã³ãã©ã«ããå®è¡ããããã¨ã«ãªãã¾ã(ããã¯ã¹ããªã¼ãã³ã°ãå®è£ ããã®ã«ä½¿ããã¾ãã"æ»ãå¤"ã®é ãåç §ãã¦ãã ããã) ããã£ã¨åæ§ã«ãã¹ãã¼ã¿ã¹ã³ã¼ãããã³ããããã»ããã§ãã¾ãã ``` ruby get '/foo' do status 418 headers \ "Allow" => "BREW, POST, GET, PROPFIND, WHEN", "Refresh" => "Refresh: 20; http://www.ietf.org/rfc/rfc2324.txt" body "I'm a tea pot!" end ``` å¼æ°ãä¼´ããªã`body`ã`headers`ã`status`ãªã©ã¯ããããã®ç¾å¨ã®å¤ã«ã¢ã¯ã»ã¹ããããã«ä½¿ãã¾ãã ### ã¹ããªã¼ãã³ã°ã¬ã¹ãã³ã¹(Streaming Responses) ã¬ã¹ãã³ã¹ããã£ã®é¨åãæªã çæãã¦ãã段éã§ããã¼ã¿ãéãåºãããã¨ãããã¨ãããã¾ãã極端ãªä¾ã§ã¯ãã¯ã©ã¤ã¢ã³ããã³ãã¯ã·ã§ã³ãéããã¾ã§ãã¼ã¿ãéãç¶ããããã¨ãããã¾ãã`stream`ãã«ãã¼ã使ãã°ãç¬èªã©ããã¼ãä½ãå¿ è¦ã¯ããã¾ããã ``` ruby get '/' do stream do |out| out << "ããã¯ä¼ -\n" sleep 0.5 out << " (å°ãå¾ ã¤) \n" sleep 1 out << "- 説ã«ãªãï¼\n" end end ``` ããã¯ã¹ããªã¼ãã³ã°APIã[Server Sent Events](http://dev.w3.org/html5/eventsource/)ã®å®è£ ãå¯è½ã«ãã[WebSockets](http://en.wikipedia.org/wiki/WebSocket)ã®åå°ã«ä½¿ããã¨ãã§ãã¾ããã¾ããä¸é¨ã®ã³ã³ãã³ããé ããªã½ã¼ã¹ã«ä¾åãã¦ããã¨ãã«ãã¹ã«ã¼ããããä¸ããããã«ä½¿ããã¨ãã§ãã¾ãã ãã¼ã: ã¹ããªã¼ãã³ã°ã®æåãç¹ã«ä¸¦è¡ãªã¯ã¨ã¹ã(cuncurrent requests)ã®æ°ã¯ãã¢ããªã±ã¼ã·ã§ã³ãæä¾ããã®ã«ä½¿ãããWebãµã¼ãã«å¼·ãä¾åãã¾ããWEBRickãå«ãããã¤ãã®ãµã¼ãã¯ãã¹ããªã¼ãã³ã°ãå ¨ããµãã¼ããã¾ããããµã¼ããã¹ããªã¼ãã³ã°ããµãã¼ãããªãå ´åãããã£ã¯`stream`ã«æ¸¡ããããããã¯ã®å®è¡ãçµäºããå¾ãä¸åº¦ã«å ¨é¨éããããã¨ã«ãªãã¾ããã¹ããªã¼ãã³ã°ã¯ãShotgunã使ã£ãå ´åã¯å ¨ãåä½ãã¾ããã ãªãã·ã§ã³å¼æ°ã`keep_open`ã«ã»ããããã¦ããå ´åãã¹ããªã¼ã ãªãã¸ã§ã¯ãä¸ã§`close`ã¯å¼ã°ãããå®è¡ããã¼ã®ä»»æã®é ããã¿ã¤ãã³ã°ã§ã¦ã¼ã¶ããããéãããã¨ãå¯è½ã«ãã¾ããããã¯ThinãRainbowsã®ãããªã¤ãã³ãåãµã¼ãä¸ã§ããæ©è½ãã¾ãããä»ã®ãµã¼ãã§ã¯ä¾ç¶ã¹ããªã¼ã ã¯éãããã¾ãã ``` ruby # ãã³ã°ãã¼ãªã³ã° set :server, :thin connections = [] get '/subscribe' do # ãµã¼ãã¤ãã³ãã«ãããã¯ã©ã¤ã¢ã³ãã®é¢å¿ãç»é² stream(:keep_open) do |out| connections << out # æ»ãã§ããã³ãã¯ã·ã§ã³ãæé¤ connections.reject!(&:closed?) end end post '/message' do connections.each do |out| # ã¯ã©ã¤ã¢ã³ãã¸æ°è¦ã¡ãã»ã¼ã¸å°çã®éç¥ out << params['message'] << "\n" # ã¯ã©ã¤ã¢ã³ãã¸ã®åæ¥ç¶ã®æ示 out.close end # è¯å®å¿ç "message received" end ``` ### ãã®ã³ã°(Logging) ãªã¯ã¨ã¹ãã¹ã³ã¼ãã«ããã¦ã`logger`ãã«ãã¼ã¯`Logger`ã¤ã³ã¹ã¿ã³ã¹ãä½ãåºãã¾ãã ``` ruby get '/' do logger.info "loading data" # ... end ``` ãã®ãã¬ã¼ã¯ãèªåã§Rackãã³ãã©ã®ãã®ã³ã°è¨å®ãåç §ãã¾ãããã®ã³ã°ãç¡å¹(disabled)ã«ããã¦ããå ´åããã®ã¡ã½ããã¯ããã¼ãªãã¸ã§ã¯ããè¿ãã®ã§ãã«ã¼ãã£ã³ã°ããã£ã«ã¿ã«ããã¦ç¹ã«å¿é ãããã¨ã¯ããã¾ããã ãã¼ã: ãã®ã³ã°ã¯ã`Sinatra::Application`ã«å¯¾ãã¦ã®ã¿ããã©ã«ãã§æå¹ã«ããã¦ããã®ã§ã`Sinatra::Base`ãç¶æ¿ãã¦ããå ´åã¯ãã¦ã¼ã¶ããããæå¹åããå¿ è¦ãããã¾ãã ``` ruby class MyApp < Sinatra::Base configure :production, :development do enable :logging end end ``` ãã®ã³ã°ããã«ã¦ã§ã¢ãè¨å®ããã¦ãã¾ãã®ãé¿ããã«ã¯ã`logging`è¨å®ã`nil`ã«ã»ãããã¾ããããããã®å ´åã`logger`ã`nil`ãè¿ããã¨ãå¿ããªãããã«ãããããã¦ã¼ã¹ã±ã¼ã¹ã¯ããªãªã¸ãã«ã®ãã¬ã¼ãã»ãããããã¨ãã§ããSinatraã¯ãã¨ã«ãã`env['rack.logger']`ã§è¦ã¤ãããã®ã使ãã¾ãã ### MIMEã¿ã¤ã(Mime Types) `send_file`ãéçãã¡ã¤ã«ã使ãæãSinatraãMIMEã¿ã¤ããç解ã§ããªãå ´åãããã¾ãããã®æ㯠`mime_type` ã使ã£ã¦ãã¡ã¤ã«æ¡å¼µåæ¯ã«ç»é²ãã¦ä¸ããã ``` ruby configure do mime_type :foo, 'text/foo' end ``` ããã¯`content_type`ãã«ãã¼ã§å©ç¨ãããã¨ãã§ãã¾ã: ``` ruby get '/' do content_type :foo "foo foo foo" end ``` ### URLã®çæ URLãçæããããã«ã¯`url`ãã«ãã¼ã¡ã½ããã使ãã¾ããHamlã§ã¯ãã®ããã«ãã¾ãã ``` ruby %a{:href => url('/foo')} foo ``` ããã¯ãªãã¼ã¹ãããã·ããã³Rackã«ã¼ãã£ã³ã°ããããããããã°èæ ®ã«å ¥ãã¾ãã ãã®ã¡ã½ããã«ã¯`to`ã¨ããã¨ã¤ãªã¢ã¹ãããã¾ã(以ä¸ã®ä¾ãåç §)ã ### ãã©ã¦ã¶ãªãã¤ã¬ã¯ã(Browser Redirect) `redirect` ãã«ãã¼ã¡ã½ããã使ããã¨ã§ããã©ã¦ã¶ããªãã¤ã¬ã¯ãããããã¨ãã§ãã¾ãã ``` ruby get '/foo' do redirect to('/bar') end ``` ä»ã«è¿½å ããããã©ã¡ã¼ã¿ã¯ã`halt`ã«æ¸¡ãããå¼æ°ã¨åæ§ã«åãæ±ããã¾ãã ``` ruby redirect to('/bar'), 303 redirect 'http://google.com', 'wrong place, buddy' ``` ã¾ãã`redirect back`ã使ãã°ãç°¡åã«ã¦ã¼ã¶ãæ¥ããã¼ã¸ã¸æ»ããªãã¤ã¬ã¯ããä½ãã¾ãã ``` ruby get '/foo' do "<a href='/bar'>do something</a>" end get '/bar' do do_something redirect back end ``` redirectã«å¼æ°ã渡ãã«ã¯ããããã¯ã¨ãªã¼ã«è¿½å ãããã ``` ruby redirect to('/bar?sum=42') ``` ã¾ãã¯ãã»ãã·ã§ã³ã使ãã¾ãã ``` ruby enable :sessions get '/foo' do session[:secret] = 'foo' redirect to('/bar') end get '/bar' do session[:secret] end ``` ### ãã£ãã·ã¥å¶å¾¡(Cache Control) ããããæ£ããè¨å®ãããã¨ããé©åãªHTTPãã£ãã·ã³ã°ã®ããã®åºç¤ã¨ãªãã¾ãã ãã£ãã·ã¥å¶å¾¡ããã(Cache-Control header)ã¯ã次ã®ããã«ç°¡åã«è¨å®ã§ãã¾ãã ``` ruby get '/' do cache_control :public "ãã£ãã·ã¥ãã¾ãã!" end ``` ãã³ã: ãã£ãã·ã³ã°ãbeforeãã£ã«ã¿å ã§è¨å®ãã¾ãã ``` ruby before do cache_control :public, :must_revalidate, :max_age => 60 end ``` `expires`ãã«ãã¼ã対å¿ãããããã«ä½¿ã£ã¦ããå ´åã¯ããã£ãã·ã¥å¶å¾¡ã¯èªåã§è¨å®ããã¾ãã ``` ruby before do expires 500, :public, :must_revalidate end ``` ãã£ãã·ã¥ãé©åã«ä½¿ãããã«ã`etag`ã¾ãã¯`last_modified`ã使ããã¨ãæ¤è¨ãã¦ãã ããããããã®ãã«ãã¼ããéãä»äºãããã *å* ã«å¼ã¶ãã¨ãæ¨å¥¨ãã¾ããããããã°ãã¯ã©ã¤ã¢ã³ããæ¢ã«ãã£ãã·ã¥ã«ææ°çãæã£ã¦ããå ´åã¯ã¬ã¹ãã³ã¹ãç´ã¡ã«ç ´æ£ããããã«ãªãã¾ãã ``` ruby get '/article/:id' do @article = Article.find params['id'] last_modified @article.updated_at etag @article.sha1 erb :article end ``` ã¾ãã[weak ETag](http://ja.wikipedia.org/wiki/HTTP_ETag#Strong_and_weak_validation)ã使ããã¨ãã§ãã¾ãã ``` ruby etag @article.sha1, :weak ``` ãããã®ãã«ãã¼ã¯ããã£ãã·ã³ã°ããã¦ããã¾ããããå¿ è¦ãªæ å ±ããã£ãã·ã¥ã«ä¸ãã¦ããã¾ããããææ©ããªãã¼ã¹ãããã·ãã£ãã·ã³ã°ã®è§£æ±ºçããæ¢ããªãã [rack-cache](https://github.com/rtomayko/rack-cache)ã試ãã¦ãã ããã ``` ruby require "rack/cache" require "sinatra" use Rack::Cache get '/' do cache_control :public, :max_age => 36000 sleep 5 "hello" end ``` `:static_cache_control`è¨å®(以ä¸ãåç §)ãããã£ãã·ã¥å¶å¾¡ãããæ å ±ãéçãã¡ã¤ã«ã«è¿½å ããããã«ä½¿ã£ã¦ãã ããã RFC 2616ã«ããã°ãã¢ããªã±ã¼ã·ã§ã³ã¯ãIf-Matchã¾ãã¯If-None-Matchãããã`*`ã«è¨å®ããã¦ããå ´åã«ã¯ãè¦æ±ããããªã½ã¼ã¹ãæ¢ã«åå¨ãããå¦ãã«å¿ãã¦ãç°ãªãæ¯ãèãããã¹ãã¨ãªã£ã¦ãã¾ããSinatraã¯ãgetã®ãããªå®å ¨ãªãªã¯ã¨ã¹ãããã³putã®ãããªåªçãªãªã¯ã¨ã¹ãã¯æ¢ã«åå¨ãã¦ãããã®ã¨ãã¦ä»®å®ããä¸æ¹ã§ãä»ã®ãªã½ã¼ã¹(ä¾ãã°ãpostãªã¯ã¨ã¹ã)ã¯æ°ããªãªã½ã¼ã¹ã¨ãã¦åãæ±ãããããä»®å®ãã¾ãããã®æ¯ãèãã¯ã`:new_resource`ãªãã·ã§ã³ã渡ããã¨ã§å¤æ´ã§ãã¾ãã ``` ruby get '/create' do etag '', :new_resource => true Article.create erb :new_article end ``` ããã§ãWeak ETagã使ãããå ´åã¯ã`:kind`ãªãã·ã§ã³ã渡ãã¦ãã ããã ``` ruby etag '', :new_resource => true, :kind => :weak ``` ### ãã¡ã¤ã«ã®éä¿¡ ãã¡ã¤ã«ãéä¿¡ããã«ã¯ã`send_file`ãã«ãã¼ã¡ã½ããã使ãã¾ãã ``` ruby get '/' do send_file 'foo.png' end ``` ããã¯ãªãã·ã§ã³ãåããã¨ãã§ãã¾ãã ``` ruby send_file 'foo.png', :type => :jpg ``` ãªãã·ã§ã³ä¸è¦§ <dl> <dt>filename</dt> <dd>ãã¡ã¤ã«åãããã©ã«ãã¯å®éã®ãã¡ã¤ã«åã</dd> <dt>last_modified</dt> <dd>Last-Modifiedãããã®å¤ãããã©ã«ãã¯ãã¡ã¤ã«ã®mtimeã</dd> <dt>type</dt> <dd>ã³ã³ãã³ãã®ç¨®é¡ãè¨å®ããªãå ´åããã¡ã¤ã«æ¡å¼µåããé¡æ¨ãããã</dd> <dt>disposition</dt> <dd> Content-Dispositionã«ä½¿ãããã許容å¤: <tt>nil</tt> (ããã©ã«ã)ã <tt>:attachment</tt> ããã³ <tt>:inline</tt> </dd> <dt>length</dt> <dd>Content-Lengthããããããã©ã«ãã¯ãã¡ã¤ã«ãµã¤ãºã</dd> <dt>status</dt> <dd> éãããã¹ãã¼ã¿ã¹ã³ã¼ããéçãã¡ã¤ã«ãã¨ã©ã¼ãã¼ã¸ã¨ãã¦éãã¨ãã«ä¾¿å©ã Rackãã³ãã©ã§ãµãã¼ãããã¦ããå ´åã¯ãRubyããã»ã¹ããã®ã¹ããªã¼ãã³ã°ä»¥å¤ã®æ段ã使ãããããã®ãã«ãã¼ã¡ã½ããã使ãã¨ãSinatraã¯èªåã§ç¯å²ãªã¯ã¨ã¹ã(range requests)ãæ±ãã </dd> </dl> ### ãªã¯ã¨ã¹ããªãã¸ã§ã¯ãã¸ã®ã¢ã¯ã»ã¹ åä¿¡ãããªã¯ã¨ã¹ããªãã¸ã§ã¯ãã¯ã`request`ã¡ã½ãããéãã¦ãªã¯ã¨ã¹ãã¬ãã«(ãã£ã«ã¿ãã«ã¼ãã£ã³ã°ãã¨ã©ã¼ãã³ãã©)ããã¢ã¯ã»ã¹ãããã¨ãã§ãã¾ãã ``` ruby # ã¢ããªã±ã¼ã·ã§ã³ã http://example.com/example ã§åä½ãã¦ããå ´å get '/foo' do t = %w[text/css text/html application/javascript] request.accept # ['text/html', '*/*'] request.accept? 'text/xml' # true request.preferred_type(t) # 'text/html' request.body # ã¯ã©ã¤ã¢ã³ãã«ãã£ã¦éä¿¡ããããªã¯ã¨ã¹ãããã£(ä¸è¨åç §) request.scheme # "http" request.script_name # "/example" request.path_info # "/foo" request.port # 80 request.request_method # "GET" request.query_string # "" request.content_length # request.bodyã®é·ã request.media_type # request.bodyã®ã¡ãã£ã¢ã¿ã¤ã request.host # "example.com" request.get? # true (ä»ã®åè©ã«ãå種ã¡ã½ãããã) request.form_data? # false request["some_param"] # some_paramå¤æ°ã®å¤ã[]ã¯ãã©ã¡ã¼ã¿ããã·ã¥ã®ã·ã§ã¼ãã«ãã request.referrer # ã¯ã©ã¤ã¢ã³ãã®ãªãã¡ã©ã¾ãã¯'/' request.user_agent # ã¦ã¼ã¶ã¨ã¼ã¸ã§ã³ã (:agent æ¡ä»¶ã«ãã£ã¦ä½¿ç¨ããã) request.cookies # ãã©ã¦ã¶ã¯ããã¼ã®ããã·ã¥ request.xhr? # Ajaxãªã¯ã¨ã¹ããã©ãã request.url # "http://example.com/example/foo" request.path # "/example/foo" request.ip # ã¯ã©ã¤ã¢ã³ãã®IPã¢ãã¬ã¹ request.secure? # false (sslã§ã¯trueã«ãªã) request.forwarded? # true (ãªãã¼ã¹ãããã·ã®è£ã§åãã¦ããå ´å) request.env # Rackã«ãã£ã¦æ¸¡ãããçã®envããã·ã¥ end ``` `script_name`ã`path_info`ãªã©ã®ãªãã·ã§ã³ã¯æ¬¡ã®ããã«å©ç¨ãããã¨ãã§ãã¾ãã ``` ruby before { request.path_info = "/" } get "/" do "å ¨ã¦ã®ãªã¯ã¨ã¹ãã¯ããã«æ¥ã" end ``` `request.body`ã¯IOã¾ãã¯StringIOã®ãªãã¸ã§ã¯ãã§ãã ``` ruby post "/api" do request.body.rewind # æ¢ã«èªã¾ãã¦ããã¨ãã®ãã data = JSON.parse request.body.read "Hello #{data['name']}!" end ``` ### ã¢ã¿ããã¡ã³ã(Attachments) `attachment`ãã«ãã¼ã使ã£ã¦ãã¬ã¹ãã³ã¹ããã©ã¦ã¶ã«è¡¨ç¤ºãããã®ã§ã¯ãªãããã£ã¹ã¯ã«ä¿åããããã¨ããã©ã¦ã¶ã«å¯¾ãéç¥ãããã¨ãã§ãã¾ãã ``` ruby get '/' do attachment "ä¿åãã¾ãã!" end ``` ãã¡ã¤ã«åã渡ããã¨ãã§ãã¾ãã ``` ruby get '/' do attachment "info.txt" "ä¿åãã¾ãã!" end ``` ### æ¥ä»ã¨æå»ã®åãæ±ã Sinatraã¯`time_for`ãã«ãã¼ã¡ã½ãããæä¾ãã¦ãããããã¯ä¸ããããå¤ããTimeãªãã¸ã§ã¯ããçæãã¾ããããã¯ã¾ã`DateTime`ã`Date`ããã³é¡ä¼¼ã®ã¯ã©ã¹ãå¤æã§ãã¾ãã ``` ruby get '/' do pass if Time.now > time_for('Dec 23, 2012') "ã¾ã æéããã" end ``` ãã®ã¡ã½ããã¯ã`expires`ã`last_modified`ã¨ãã£ã種é¡ã®ãã®ã®å é¨ã§ä½¿ããã¦ãã¾ãããã®ãããã¢ããªã±ã¼ã·ã§ã³ã«ããã¦ã`time_for`ããªã¼ãã¼ã©ã¤ããããã¨ã§ãããã®ã¡ã½ããã®æåãç°¡åã«æ¡å¼µã§ãã¾ãã ``` ruby helpers do def time_for(value) case value when :yesterday then Time.now - 24*60*60 when :tomorrow then Time.now + 24*60*60 else super end end end get '/' do last_modified :yesterday expires :tomorrow "hello" end ``` ### ãã³ãã¬ã¼ããã¡ã¤ã«ã®æ¢ç´¢ `find_template`ãã«ãã¼ã¯ãã¬ã³ããªã³ã°ã®ããã®ãã³ãã¬ã¼ããã¡ã¤ã«ãè¦ã¤ããããã«ä½¿ããã¾ãã ``` ruby find_template settings.views, 'foo', Tilt[:haml] do |file| puts "could be #{file}" end ``` ãã®ä¾ã¯ãã¾ãæçã§ã¯ããã¾ããããããããã®ã¡ã½ããããç¬èªã®æ¢ç´¢æ©æ§ã§åããããªã¼ãã¼ã©ã¤ããããªãæçã«ãªãã¾ããä¾ãã°ãè¤æ°ã®ãã¥ã¼ãã£ã¬ã¯ããªã使ããããã«ãããã¨ããããã¾ãã ``` ruby set :views, ['views', 'templates'] helpers do def find_template(views, name, engine, &block) Array(views).each { |v| super(v, name, engine, &block) } end end ``` ä»ã®ä¾ã¨ãã¦ã¯ãç°ãªãã¨ã³ã¸ã³ç¨ã®ç°ãªããã£ã¬ã¯ããªã使ãå ´åã§ãã ``` ruby set :views, :sass => 'views/sass', :haml => 'templates', :default => 'views' helpers do def find_template(views, name, engine, &block) _, folder = views.detect { |k,v| engine == Tilt[k] } folder ||= views[:default] super(folder, name, engine, &block) end end ``` ãããã¨ã¯ã¹ãã³ã·ã§ã³ã¨ãã¦æ¸ãã¦ãä»ã®äººã¨ç°¡åã«å ±æãããã¨ãã§ãã¾ãï¼ ãã¼ã: `find_template`ã¯ãã¡ã¤ã«ãå®éã«åå¨ãããã®ãã§ãã¯ããã¾ããããä¸ãããããããã¯ããã¹ã¦ã®å¯è½ãªãã¹ã«å¯¾ãå¼ã³åºãã¾ãããããããã©ã¼ãã³ã¹ä¸ã®åé¡ã«ã¯ãªããªãã®ã¯ã`render`ã¯ãã¡ã¤ã«ãè¦ã¤ããã¨ç´ã¡ã«`break`ã使ãããã§ããã¾ãããã³ãã¬ã¼ãã®å ´æï¼ããã³å 容ï¼ã¯ãdevelopmentã¢ã¼ãã§ã®èµ·åã§ãªãéãã¯ãã£ãã·ã¥ããã¾ãããã®ãã¨ã¯ãè¤éãªã¡ã½ãã(a really crazy method)ãæ¸ããå ´åã¯è¨æ¶ãã¦ããå¿ è¦ãããã¾ãã ## ã³ã³ãã£ã®ã¥ã¬ã¼ã·ã§ã³(Configuration) ã©ã®ç°å¢ã§ãèµ·åæã«ï¼åã ãå®è¡ããã¾ãã ``` ruby configure do # ï¼ã¤ã®ãªãã·ã§ã³ãã»ãã set :option, 'value' # è¤æ°ã®ãªãã·ã§ã³ãã»ãã set :a => 1, :b => 2 # `set :option, true`ã¨åã enable :option # `set :option, false`ã¨åã disable :option # ãããã¯ã使ã£ã¦åçãªè¨å®ããããã¨ãã§ãã¾ãã set(:css_dir) { File.join(views, 'css') } end ``` ç°å¢è¨å®(`RACK_ENV`ç°å¢å¤æ°)ã`:production`ã«è¨å®ããã¦ããæã ãå®è¡ããæ¹æ³: ``` ruby configure :production do ... end ``` ç°å¢è¨å®ã`:production`ã`:test`ã«è¨å®ããã¦ããæã ãå®è¡ããæ¹æ³: ``` ruby configure :production, :test do ... end ``` è¨å®ãããªãã·ã§ã³ã«ã¯`settings`ããã¢ã¯ã»ã¹ã§ãã¾ã: ``` ruby configure do set :foo, 'bar' end get '/' do settings.foo? # => true settings.foo # => 'bar' ... end ``` ### æ»æé²å¾¡ã«å¯¾ããè¨å® Sinatraã¯ã[Rack::Protection](https://github.com/rkh/rack-protection#readme)ã使ã£ã¦ãã¢ããªã±ã¼ã·ã§ã³ãå¤çºããæ¥åè¦çæ»æããå®ã£ã¦ãã¾ãããã®æåã¯ç°¡åã«ç¡å¹åã§ãã¾ã(ããã¯ã¢ããªã±ã¼ã·ã§ã³ã大éã®èå¼±æ§æ»æã«æããã¨ã«ãªãã¾ã)ã ``` ruby disable :protection ``` åä¸ã®é²å¾¡å±¤ãå¤ãããã«ã¯ã`protection`ããªãã·ã§ã³ããã·ã¥ã«ã»ãããã¾ãã ``` ruby set :protection, :except => :path_traversal ``` ã¾ãé åã渡ãã¦ãè¤æ°ã®é²å¾¡ãç¡å¹ã«ãããã¨ãã§ãã¾ãã ``` ruby set :protection, :except => [:path_traversal, :session_hijacking] ``` ããã©ã«ãã§Sinatraã¯ã`:sessions`ãæå¹ã«ãªã£ã¦ããå ´åãã»ãã·ã§ã³ãã¼ã¹ã®é²å¾¡ã ããè¨å®ãã¾ããããããèªèº«ã§ã»ãã·ã§ã³ãè¨å®ãããå ´åãããã¾ãããã®å ´åã¯ã`:session`ãªãã·ã§ã³ã渡ããã¨ã«ãããã»ãã·ã§ã³ãã¼ã¹ã®é²å¾¡ãè¨å®ãããã¨ãã§ãã¾ãã ``` ruby use Rack::Session::Pool set :protection, :session => true ``` ### å©ç¨å¯è½ãªè¨å® <dl> <dt>absolute_redirects</dt> <dd> ç¡å¹ã®ã¨ããSinatraã¯ç¸å¯¾ãªãã¤ã¬ã¯ãã許容ããããRFC 2616 (HTTP 1.1)ã¯çµ¶å¯¾ãªãã¤ã¬ã¯ãã®ã¿ã許容ããã®ã§ãããã«ã¯æºæ ããªããªãã </dd> <dd> ã¢ããªã±ã¼ã·ã§ã³ããé©åã«è¨å®ããã¦ããªããªãã¼ã¹ãããã·ã®è£ã§èµ°ã£ã¦ããå ´åã¯æå¹ããã¼ã: <tt>url</tt>ãã«ãã¼ã¯ã第ï¼å¼æ°ã«<tt>false</tt>ã渡ããªãéããä¾ç¶ã¨ãã¦çµ¶å¯¾URLãçæããã </dd> <dd>ããã©ã«ãã¯ç¡å¹ã</dd> <dt>add_charset</dt> <dd> Mimeã¿ã¤ã <tt>content_type</tt>ãã«ãã¼ãèªåçã«ãã£ã©ã¯ã¿ã»ããæ å ±ãããã«è¿½å ããããã®ãªãã·ã§ã³ã¯æ¸ãæããã®ã§ã¯ãªããå¤ã追å ããããã«ãããã¨ã <tt>settings.add_charset << "application/foobar"</tt> </dd> <dt>app_file</dt> <dd> ã¡ã¤ã³ã®ã¢ããªã±ã¼ã·ã§ã³ãã¡ã¤ã«ã®ãã¹ã§ãããããã¸ã§ã¯ãã®ã«ã¼ããviewsããã³publicãã©ã«ããè¦ã¤ããããã«ä½¿ãããã </dd> <dt>bind</dt> <dd>ãã¤ã³ãããIPã¢ãã¬ã¹(ããã©ã«ã: `environment`ãdevelopmentã«ã»ããããã¦ããã¨ãã¯ã<tt>0.0.0.0</tt> <em>ã¾ãã¯</em> <tt>localhost</tt>)ããã«ãã¤ã³ãµã¼ãã§ã®ã¿ä½¿ãããã</dd> <dt>default_encoding</dt> <dd>ä¸æãªã¨ãã«ä»®å®ãããã¨ã³ã³ã¼ãã£ã³ã°(ããã©ã«ãã¯<tt>"utf-8"</tt>)ã</dd> <dt>dump_errors</dt> <dd>ãã°ã«ãããã¨ã©ã¼ã®è¡¨ç¤ºã</dd> <dt>environment</dt> <dd> ç¾å¨ã®ç°å¢ãããã©ã«ãã¯<tt>ENV['RACK_ENV']</tt>ããããç¡ãå ´åã¯<tt>"development"</tt>ã </dd> <dt>logging</dt> <dd>ãã¬ã¼ã®ä½¿ç¨ã</dd> <dt>lock</dt> <dd> åãªã¯ã¨ã¹ãå¨ãã®ããã¯ã®é ç½®ã§ãRubyããã»ã¹ãã¨ã«ãªã¯ã¨ã¹ãå¦çã並è¡ãã¦èµ°ãããããã«ããã </dd> <dd>ã¢ããªã±ã¼ã·ã§ã³ãã¹ã¬ããã»ã¼ãã§ãªããã°æå¹ãããã©ã«ãã¯ç¡å¹ã</dd> <dt>method_override</dt> <dd> put/deleteãã©ã¼ã ãããããããµãã¼ãããªããã©ã¦ã¶ã§ä½¿ããããã«<tt>_method</tt>ã®ãã¾ããªãã使ããããã«ããã </dd> <dt>port</dt> <dd>å¾ ã¡åããã¼ãããã«ãã¤ã³ãµã¼ãã®ã¿ã§æå¹ã</dd> <dt>prefixed_redirects</dt> <dd> 絶対ãã¹ãä¸ãããã¦ããªãã¨ãã«ããªãã¤ã¬ã¯ãã«<tt>request.script_name</tt>ãæ¿å ¥ãããå¦ãã®è¨å®ãããã«ãã<tt>redirect '/foo'</tt>ã¯ã<tt>redirect to('/foo')</tt>ã®ããã«æ¯ãèããããã©ã«ãã¯ç¡å¹ã </dd> <dt>protection</dt> <dd>Webæ»æé²å¾¡ãæå¹ã«ãããå¦ãã®è¨å®ãä¸è¿°ã®æ»æé²å¾¡ã®é ãåç §ã</dd> <dt>public_dir</dt> <dd><tt>public_folder</tt>ã®ã¨ã¤ãªã¢ã¹ã以ä¸ãåç §ã</dd> <dt>public_folder</dt> <dd> publicãã¡ã¤ã«ãæä¾ããããã£ã¬ã¯ããªã®ãã¹ãéçãã¡ã¤ã«ã®æä¾ãæå¹ã«ãªã£ã¦ããå ´åã«ã®ã¿ä½¿ããã (以ä¸ã®<tt>static</tt>è¨å®ãåç §)ãè¨å®ããã¦ããªãå ´åã<tt>app_file</tt>è¨å®ããæ¨å®ã </dd> <dt>reload_templates</dt> <dd> ãªã¯ã¨ã¹ãéã§ãã³ãã¬ã¼ããåãã¼ããããå¦ãã®è¨å®ãdevelopmentã¢ã¼ãã§ã¯æå¹ã </dd> <dt>root</dt> <dd> ããã¸ã§ã¯ãã®ã«ã¼ããã£ã¬ã¯ããªã®ãã¹ãè¨å®ããã¦ããªãå ´åã<tt>app_file</tt>è¨å®ããæ¨å®ã </dd> <dt>raise_errors</dt> <dd> ä¾å¤çºçã®è¨å®(ã¢ããªã±ã¼ã·ã§ã³ã¯æ¢ã¾ã)ã<tt>environment</tt>ã<tt>"test"</tt>ã«è¨å®ããã¦ããã¨ãã¯ããã©ã«ãã¯æå¹ããã以å¤ã¯ç¡å¹ã </dd> <dt>run</dt> <dd> æå¹ã®ã¨ããSinatraãWebãµã¼ãã®èµ·åãåãæ±ããrackupã¾ãã¯ä»ã®æ段ã使ãã¨ãã¯æå¹ã«ããªããã¨ã </dd> <dt>running</dt> <dd>ãã«ãã¤ã³ãµã¼ãã稼åä¸ãï¼ãã®è¨å®ãå¤æ´ããªããã¨ï¼</dd> <dt>server</dt> <dd> ãã«ãã¤ã³ãµã¼ãã¨ãã¦ä½¿ç¨ãããµã¼ãã¾ãã¯ãµã¼ã群ã®æå®ãæå®é ä½ã¯åªå 度ã表ããããã©ã«ãã¯Rubyå®è£ ã«ä¾åã </dd> <dt>sessions</dt> <dd> <tt>Rack::Session::Cookie</tt>ã使ã£ãã¯ããã¼ãã¼ã¹ã®ã»ãã·ã§ã³ãµãã¼ãã®æå¹åã詳ããã¯ã'ã»ãã·ã§ã³ã®ä½¿ç¨'ã®é ãåç §ã®ãã¨ã </dd> <dt>show_exceptions</dt> <dd> ä¾å¤çºçæã«ãã©ã¦ã¶ã«ã¹ã¿ãã¯ãã¬ã¼ã¹ã表示ããã<tt>environment</tt>ã<tt>"development"</tt>ã«è¨å®ããã¦ããã¨ãã¯ãããã©ã«ãã§æå¹ããã以å¤ã¯ç¡å¹ã </dd> <dd> ã¾ãã<tt>:after_handler</tt>ãã»ãããããã¨ãã§ããããã«ããããã©ã¦ã¶ã«ã¹ã¿ãã¯ãã¬ã¼ã¹ã表示ããåã«ãã¢ããªã±ã¼ã·ã§ã³åºæã®ã¨ã©ã¼ãã³ããªã³ã°ãèµ·åãããããã </dd> <dt>static</dt> <dd>Sinatraãéçãã¡ã¤ã«ã®æä¾ãåãæ±ããã®è¨å®ã</dd> <dd>ãã®åãæ±ããã§ãããµã¼ãã使ãå ´åã¯ç¡å¹ã</dd> <dd>ç¡å¹åã§ããã©ã¼ãã³ã¹ã¯æ¹åãã</dd> <dd> ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã§ã¯ããã©ã«ãã§æå¹ãã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã§ã¯ç¡å¹ã </dd> <dt>static_cache_control</dt> <dd> Sinatraãéçãã¡ã¤ã«ãæä¾ããã¨ããããã»ãããã¦ãã¬ã¹ãã³ã¹ã«<tt>Cache-Control</tt>ãããã追å ããããã«ããã<tt>cache_control</tt>ãã«ãã¼ã使ããã¨ãããã©ã«ãã¯ç¡å¹ã </dd> <dd> è¤æ°ã®å¤ãã»ããããã¨ãã¯æ示çã«é åã使ã: <tt>set :static_cache_control, [:public, :max_age => 300]</tt> </dd> <dt>threaded</dt> <dd> <tt>true</tt>ã«è¨å®ããã¦ããã¨ãã¯ãThinã«ãªã¯ã¨ã¹ããå¦çããããã«<tt>EventMachine.defer</tt>ã使ããã¨ãéç¥ããã </dd> <dt>views</dt> <dd> ãã¥ã¼ãã£ã¬ã¯ããªã®ãã¹ãè¨å®ããã¦ããªãå ´åã<tt>app_file</tt>è¨å®ããæ¨å®ããã </dd> <dt>x_cascade</dt> <dd> ãããããã«ã¼ãã£ã³ã°ãç¡ãå ´åã«ãX-Cascadeããããã»ãããããå¦ãã®è¨å®ãããã©ã«ãã¯<tt>true</tt>ã </dd> </dl> ## ç°å¢è¨å®(Environments) ï¼ç¨®é¡ã®æ¢å®ç°å¢ã`"development"`ã`"production"`ããã³`"test"`ãããã¾ããç°å¢ã¯ã`RACK_ENV`ç°å¢å¤æ°ãéãã¦è¨å®ã§ãã¾ããããã©ã«ãå¤ã¯ã`"development"`ã§ãã`"development"`ç°å¢ã«ããã¦ããã¹ã¦ã®ãã³ãã¬ã¼ãã¯ãåãªã¯ã¨ã¹ãéã§åãã¼ããããããã¦ãç¹å¥ã®`not_found`ããã³`error`ãã³ãã©ããã©ã¦ã¶ã«ã¹ã¿ãã¯ãã¬ã¼ã¹ã表示ãã¾ãã`"production"`ããã³`"test"`ç°å¢ã«ããã¦ã¯ããã³ãã¬ã¼ãã¯ããã©ã«ãã§ãã£ãã·ã¥ããã¾ãã ç°ãªãç°å¢ãèµ°ãããã«ã¯ã`RACK_ENV`ç°å¢å¤æ°ãè¨å®ãã¾ãã ``` shell RACK_ENV=production ruby my_app.rb ``` æ¢å®ã¡ã½ããã`development?`ã`test?`ããã³`production?`ããç¾å¨ã®ç°å¢è¨å®ã確èªããããã«ä½¿ãã¾ãã ``` ruby get '/' do if settings.development? "development!" else "not development!" end end ``` ## ã¨ã©ã¼ãã³ããªã³ã°(Error Handling) ã¨ã©ã¼ãã³ãã©ã¯ã«ã¼ãã£ã³ã°ããã³beforeãã£ã«ã¿ã¨åãã³ã³ããã¹ãã§å®è¡ããã¾ããããªãã¡ããã¯ã`haml`ã`erb`ã`halt`ã¨ãã£ã便å©ãªãã®ãå ¨ã¦ä½¿ãããã¨ãæå³ãã¾ãã ### æªæ¤åº(Not Found) `Sinatra::NotFound`ä¾å¤ãçºçããã¨ããã¾ãã¯ã¬ã¹ãã³ã¹ã®ã¹ãã¼ã¿ã¹ã³ã¼ãã404ã®ã¨ãã«ã`not_found`ãã³ãã©ãçºåãã¾ãã ``` ruby not_found do 'ãã¡ã¤ã«ãåå¨ãã¾ãã' end ``` ### ã¨ã©ã¼(Error) `error`ãã³ãã©ã¯ã«ã¼ãã£ã³ã°ãããã¯ã¾ãã¯ãã£ã«ã¿å ã§ä¾å¤ãçºçããã¨ãã¯ãã¤ã§ãçºåãã¾ããä¾å¤ãªãã¸ã§ã¯ãã¯Rackå¤æ°`sinatra.error`ããåå¾ã§ãã¾ãã ``` ruby error do 'ã¨ã©ã¼ãçºçãã¾ããã - ' + env['sinatra.error'].message end ``` ã¨ã©ã¼ãã«ã¹ã¿ãã¤ãºããå ´åã¯ã ``` ruby error MyCustomError do 'ã¨ã©ã¼ã¡ãã»ã¼ã¸...' + env['sinatra.error'].message end ``` ã¨æ¸ãã¦ããã¦ãä¸è¨ã®ããã«å¼ã³åºãã¾ãã ``` ruby get '/' do raise MyCustomError, 'ä½ããã¾ããã£ãããã§ã' end ``` ããããã¨ãããªãã¾ãã ``` ã¨ã©ã¼ã¡ãã»ã¼ã¸... ä½ããã¾ããã£ãããã§ã ``` ãããã¯ãã¹ãã¼ã¿ã¹ã³ã¼ãã«å¯¾å¿ããã¨ã©ã¼ãã³ãã©ãè¨å®ãããã¨ãã§ãã¾ãã ``` ruby error 403 do 'Access forbidden' end get '/secret' do 403 end ``` ç¯å²æå®ãã§ãã¾ãã ``` ruby error 400..510 do 'Boom' end ``` Sinatraãéçºç°å¢ã®ä¸ã§å®è¡ãã¦ããå ´åã¯ãç¹å¥ãª`not_found`ããã³`error`ãã³ãã©ãå°å ¥ãããããã¯è¦ªåãªã¹ã¿ãã¯ãã¬ã¼ã¹ã¨è¿½å ã®ãããã®ã³ã°æ å ±ããã©ã¦ã¶ã«è¡¨ç¤ºãã¾ãã ## Rackããã«ã¦ã§ã¢(Rack Middleware) Sinatraã¯Ruby製Webãã¬ã¼ã ã¯ã¼ã¯ã®ãããã«ãªæ¨æºçã¤ã³ã¿ãã§ã¼ã¹ã§ãã[Rack](http://rack.github.io/)ä¸ã«æ§ç¯ããã¦ãã¾ããã¢ããªã±ã¼ã·ã§ã³ãããããã¼ã«ã¨ã£ã¦Rackã«ãããæãèå³æ·±ãæ©è½ã¯ããããã«ã¦ã§ã¢(middleware)ãããµãã¼ããã¦ãããã¨ã§ãããããã¯ããµã¼ãã¨ã¢ããªã±ã¼ã·ã§ã³ã¨ã®éã«ç½®ãããHTTPãªã¯ã¨ã¹ã/ã¬ã¹ãã³ã¹ãç£è¦ããã³/ã¾ãã¯æä½ãããã¨ã§ãå種ã®æ±ç¨çæ©è½ãæä¾ããã³ã³ãã¼ãã³ãã§ãã Sinatraã¯ãããã¬ãã«ã®`use`ã¡ã½ãããéãã¦ãRackããã«ã¦ã§ã¢ãã¤ãã©ã¤ã³ã®æ§ç¯ã楽ã«ãã¾ãã ``` ruby require 'sinatra' require 'my_custom_middleware' use Rack::Lint use MyCustomMiddleware get '/hello' do 'Hello World' end ``` `use`ã®ææ³ã¯ã[Rack::Builder](http://rubydoc.info/github/rack/rack/master/Rack/Builder)DSLã§å®ç¾©ããã¦ããããï¼rackupãã¡ã¤ã«ã§æããã使ãããï¼ã¨åãã§ããä¾ãã° `use`ã¡ã½ããã¯è¤æ°ã®å¼æ°ãããã¦ãããã¯ãåããã¨ãã§ãã¾ãã ``` ruby use Rack::Auth::Basic do |username, password| username == 'admin' && password == 'secret' end ``` Rackã¯ããã®ã³ã°ããããã®ã³ã°ãURLã«ã¼ãã£ã³ã°ãèªè¨¼ãã»ãã·ã§ã³ç®¡çãªã©ãå¤æ§ãªæ¨æºçããã«ã¦ã§ã¢ãå ±ã«é å¸ããã¦ãã¾ããSinatraã¯ãã®å¤ãã®ã³ã³ãã¼ãã³ããèªåã§ä½¿ãããåºæ¬è¨å®ããã¦ãããããé常ããããã`use`ã§æ示çã«æå®ããå¿ è¦ã¯ããã¾ããã 便å©ãªããã«ã¦ã§ã¢ã以ä¸ã§è¦ã¤ãããã¾ãã [rack](https://github.com/rack/rack/tree/master/lib/rack)ã [rack-contrib](https://github.com/rack/rack-contrib#readm)ã ã¾ãã¯[Rack wiki](https://github.com/rack/rack/wiki/List-of-Middleware)ã ## ãã¹ã(Testing) Sinatraã§ã®ãã¹ãã¯Rackãã¼ã¹ã®ãã¹ãã©ã¤ãã©ãªã¾ãã¯ãã¬ã¼ã ã¯ã¼ã¯ã使ã£ã¦æ¸ããã¨ãã§ãã¾ãã[Rack::Test](http://rdoc.info/github/brynary/rack-test/master/frames)ããè¦ããã¾ãã ``` ruby require 'my_sinatra_app' require 'minitest/autorun' require 'rack/test' class MyAppTest < Minitest::Test 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 "Songbirdã使ã£ã¦ã¾ã!", last_response.body end end ``` ãã¼ã: ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã§Sinatraã使ãå ´åã¯ãä¸è¨`Sinatra::Application`ãã¢ããªã±ã¼ã·ã§ã³ã®ã¯ã©ã¹åã«ç½®ãæãã¦ãã ããã ## Sinatra::Base - ããã«ã¦ã§ã¢ãã©ã¤ãã©ãªããã³ã¢ã¸ã¥ã©ã¼ã¢ã㪠軽éãªã¢ããªã±ã¼ã·ã§ã³ã§ããã°ããããã¬ãã«ã§ã¢ããªã±ã¼ã·ã§ã³ãå®ç¾©ãã¦ãããã¨ã¯ãã¾ãããã¾ãããåå©ç¨æ§å¯è½ãªã³ã³ãã¼ãã³ããä¾ãã°Rackããã«ã¦ã§ã¢ãRailsã®Metalããµã¼ãã³ã³ãã¼ãã³ããå«ãã·ã³ãã«ãªã©ã¤ãã©ãªããããã¯Sinatraã®æ¡å¼µããã°ã©ã ãæ§ç¯ãããããªå ´åãããã¯ç¡è¦ã§ããªãæ¬ ç¹ãæã¤ãã®ã¨ãªãã¾ãããããã¬ãã«ã¯ã軽éãªã¢ããªã±ã¼ã·ã§ã³ã®ã¹ã¿ã¤ã«ã«ãããè¨å®ï¼ä¾ãã°ãåä¸ã®ã¢ããªã±ã¼ã·ã§ã³ãã¡ã¤ã«ã`./public`ããã³`./views`ãã£ã¬ã¯ããªããã®ã³ã°ãä¾å¤è©³ç´°ãã¼ã¸ãªã©ï¼ãä»®å®ãã¦ãã¾ããããã§`Sinatra::Base`ã®åºçªã§ãã ``` ruby require 'sinatra/base' class MyApp < Sinatra::Base set :sessions, true set :foo, 'bar' get '/' do 'Hello world!' end end ``` `Sinatra::Base`ã®ãµãã¯ã©ã¹ã§å©ç¨ã§ããã¡ã½ããã¯ããããã¬ãã«DSLã§å©ç¨ã§ãããã®ã¨å ¨ãåãã§ããã»ã¨ãã©ã®ãããã¬ãã«ã§è¨è¿°ãããã¢ããªã¯ã以ä¸ã®ï¼ç¹ãä¿®æ£ãããã¨ã§`Sinatra::Base`ã³ã³ãã¼ãã³ãã«å¤ãããã¨ãã§ãã¾ãã * `sinatra`ã®ä»£ããã«`sinatra/base`ãèªã¿è¾¼ã (ããããªãå ´åãSinatraã®DSLã¡ã½ããã®å ¨ã¦ãmainã®åå空éã«ã¤ã³ãã¼ãããã¾ã) * ã«ã¼ãã£ã³ã°ãã¨ã©ã¼ãã³ãã©ããã£ã«ã¿ããªãã·ã§ã³ã`Sinatra::Base`ã®ãµãã¯ã©ã¹ã«æ¸ã `Sinatra::Base`ã¯ã¾ã£ããã§ãããã«ãã¤ã³ãµã¼ããå«ããã»ã¨ãã©ã®ãªãã·ã§ã³ãããã©ã«ãã§ç¡å¹ã«ãªã£ã¦ãã¾ããå©ç¨å¯è½ãªãªãã·ã§ã³ã¨ãã®æåã®è©³ç´°ã«ã¤ãã¦ã¯[Configuring Settings](http://sinatra.github.com/configuration.html)(è±èª)ãã覧ä¸ããã ãããã¯ã©ã·ãã¯ã¹ã¿ã¤ã«ã¨åããããªæåã®ã¢ããªã±ã¼ã·ã§ã³ããããã¬ãã«ã§å®ç¾©ãããå¿ è¦ãããã°ã`Sinatra::Application`ããµãã¯ã©ã¹åããã¦ãã ããã ```ruby require "sinatra/base" class MyApp < Sinatra::Application get "/" do 'Hello world!' end end ``` ### ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã« vs ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã« ä¸è¬çèªèã¨éã£ã¦ãã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã使ããã¨ã«åé¡ã¯ãªã«ãããã¾ãããããããã®ã¢ããªã±ã¼ã·ã§ã³ã«åã£ã¦ããã®ã§ããã°ãã¢ã¸ã¥ã©ã¼ã¢ããªã±ã¼ã·ã§ã³ã«ç§»è¡ããå¿ è¦ã¯ããã¾ããã ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã使ããã«ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã使ã£ãå ´åã®ä¸çªã®ä¸å©ãªç¹ã¯ãRubyããã»ã¹ãã¨ã«ãã ä¸ã¤ã®Sinatraã¢ããªã±ã¼ã·ã§ã³ããæã¦ãªãç¹ã§ããè¤æ°ãå¿ è¦ãªå ´åã¯ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã«ç§»è¡ãã¦ãã ãããã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã¨ã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ãæ··åã§ããªãã¨ãããã¨ã¯ããã¾ããã ä¸æ¹ã®ã¹ã¿ã¤ã«ããä»æ¹ã¸ç§»è¡ããå ´åãããã©ã«ãè¨å®ããããã«ç°ãªãç¹ã«æ³¨æãå¿ è¦ã§ãã <table> <tr> <th>è¨å®</th> <th>ã¯ã©ãã·ãã¯</th> <th>ã¢ã¸ã¥ã©ã¼</th> <th>ã¢ã¸ã¥ã©ã¼</th> </tr> <tr> <td>app_file</td> <td>sinatraãèªã¿è¾¼ããã¡ã¤ã«</td> <td>Sinatra::Baseããµãã¯ã©ã¹åãããã¡ã¤ã«</td> <td>Sinatra::Applicationããµãã¯ã©ã¹åãããã¡ã¤ã«</td> </tr> <tr> <td>run</td> <td>$0 == app_file</td> <td>false</td> <td>false</td> </tr> <tr> <td>logging</td> <td>true</td> <td>false</td> <td>true</td> </tr> <tr> <td>method_override</td> <td>true</td> <td>false</td> <td>true</td> </tr> <tr> <td>inline_templates</td> <td>true</td> <td>false</td> <td>true</td> </tr> <tr> <td>static</td> <td>true</td> <td>false</td> <td>true</td> </tr> </table> ### ã¢ã¸ã¥ã©ã¼ã¢ããªã±ã¼ã·ã§ã³ã®æä¾ ã¢ã¸ã¥ã©ã¼ã¢ããªã±ã¼ã·ã§ã³ãéå§ãã¤ã¾ã`run!`ã使ã£ã¦éå§ãããäºç¨®é¡ã®ããæ¹ãããã¾ãã ``` ruby # my_app.rb require 'sinatra/base' class MyApp < Sinatra::Base # ... ã¢ããªã±ã¼ã·ã§ã³ã®ã³ã¼ããæ¸ã ... # Rubyãã¡ã¤ã«ãç´æ¥å®è¡ãããããµã¼ããç«ã¡ä¸ãã run! if app_file == $0 end ``` ã¨ãã¦ã次ã®ããã«èµ·åãããã ``` shell ruby my_app.rb ``` ã¾ãã¯ãRackãã³ãã©ã使ããããã«ãã`config.ru`ãã¡ã¤ã«ãæ¸ãã¦ã ``` ruby # config.ru (rackupã§èµ·å) require './my_app' run MyApp ``` èµ·åãã¾ãã ``` shell rackup -p 4567 ``` ### config.ruãç¨ããã¯ã©ãã·ãã¯ã¹ã¿ã¤ã«ã¢ããªã±ã¼ã·ã§ã³ã®ä½¿ç¨ ã¢ããªã±ã¼ã·ã§ã³ãã¡ã¤ã«ã¨ã ``` ruby # app.rb require 'sinatra' get '/' do 'Hello world!' end ``` 対å¿ãã`config.ru`ãæ¸ãã¾ãã ``` ruby require './app' run Sinatra::Application ``` ### config.ruã¯ãã¤ä½¿ãã®ãï¼ `config.ru`ãã¡ã¤ã«ã¯ã以ä¸ã®å ´åã«é©ãã¦ãã¾ãã * ç°ãªãRackãã³ãã©(Passenger, Unicorn, Herokuãªã©)ã§ãããã¤ãããã¨ã * `Sinatra::Base`ã®è¤æ°ã®ãµãã¯ã©ã¹ã使ãããã¨ã * Sinatraãããã«ã¦ã§ã¢ã¨ãã¦å©ç¨ããã¨ã³ããã¤ã³ãã¨ãã¦ã¯å©ç¨ããªãã¨ã **ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã«ç§»è¡ããã¨ããçç±ã ãã§ã`config.ru`ã«ç§»è¡ããå¿ è¦ã¯ãªãã`config.ru`ã§èµ·åããããã«ã¢ã¸ã¥ã©ã¼ã¹ã¿ã¤ã«ã使ãå¿ è¦ã¯ããã¾ããã** ### Sinatraã®ããã«ã¦ã§ã¢ã¨ãã¦ã®å©ç¨ Sinatraã¯ä»ã®Rackããã«ã¦ã§ã¢ãå©ç¨ãããã¨ãã§ããã ãã§ãªãã å ¨ã¦ã®Sinatraã¢ããªã±ã¼ã·ã§ã³ã¯ãããèªä½ããã«ã¦ã§ã¢ã¨ãã¦å¥ã®Rackã¨ã³ããã¤ã³ãã®åã«è¿½å ãããã¨ãå¯è½ã§ãã ãã®ã¨ã³ããã¤ã³ãã«ã¯ãå¥ã®Sinatraã¢ããªã±ã¼ã·ã§ã³ã¾ãã¯ä»ã®Rackãã¼ã¹ã®ã¢ããªã±ã¼ã·ã§ã³(Rails/Ramaze/Camping/â¦)ãç¨ããããã§ãããã ``` ruby require 'sinatra/base' class LoginScreen < Sinatra::Base enable :sessions get('/login') { haml :login } post('/login') do if params['name'] = 'admin' and params['password'] = 'admin' session['user_name'] = params['name'] else redirect '/login' end end end class MyApp < Sinatra::Base # ããã«ã¦ã§ã¢ã¯beforeãã£ã«ã¿ã®åã«å®è¡ããã use LoginScreen before do unless session['user_name'] halt "ã¢ã¯ã»ã¹ã¯æå¦ããã¾ããã<a href='/login'>ãã°ã¤ã³</a>ãã¦ãã ããã" end end get('/') { "Hello #{session['user_name']}." } end ``` ### åçãªã¢ããªã±ã¼ã·ã§ã³ã®çæ æ°ããã¢ããªã±ã¼ã·ã§ã³ãå®è¡æã«ãå®æ°ã«å²ãå½ã¦ããã¨ãªãçæããããªãå ´åãããã§ãããã`Sinatra.new`ã使ãã°ãããã§ãã¾ãã ``` ruby require 'sinatra/base' my_app = Sinatra.new { get('/') { "hi" } } my_app.run! ``` ããã¯çç¥ã§ããå¼æ°ã¨ãã¦ããããç¶æ¿ããã¢ããªã±ã¼ã·ã§ã³ãåãã¾ãã ```ruby # config.ru (rackupã§èµ·å) require 'sinatra/base' controller = Sinatra.new do enable :logging helpers MyHelpers end map('/a') do run Sinatra.new(controller) { get('/') { 'a' } } end map('/b') do run Sinatra.new(controller) { get('/') { 'b' } } end ``` ããã¯ç¹ã«Sinatraã®extensionããã¹ãããã¨ãããSinatraãèªèº«ã®ã©ã¤ãã©ãªã§å©ç¨ããå ´åã«å½¹ç«ã¡ã¾ãã ããã¯ã¾ããSinatraãããã«ã¦ã§ã¢ã¨ãã¦å©ç¨ãããã¨ã極ãã¦ç°¡åã«ãã¾ãã ``` ruby require 'sinatra/base' use Sinatra do get('/') { ... } end run RailsProject::Application ``` ## ã¹ã³ã¼ãã¨ãã¤ã³ãã£ã³ã°(Scopes and Binding) ç¾å¨ã®ã¹ã³ã¼ãã¯ã©ã®ã¡ã½ãããå¤æ°ãå©ç¨å¯è½ãã決å®ãã¾ãã ### ã¢ããªã±ã¼ã·ã§ã³/ã¯ã©ã¹ã®ã¹ã³ã¼ã å ¨ã¦ã®Sinatraã¢ããªã±ã¼ã·ã§ã³ã¯Sinatra::Baseã®ãµãã¯ã©ã¹ã«ç¸å½ãã¾ãã ãããããã¬ãã«DSLãå©ç¨ãã¦ãããªãã°(`require 'sinatra'`)ãã®ã¯ã©ã¹ã¯Sinatra::Applicationã§ããã ããã§ãªããã°ãããªããæ示çã«ä½æãããµãã¯ã©ã¹ã§ãã ã¯ã©ã¹ã¬ãã«ã§ã¯`get`ã`before`ã®ãããªã¡ã½ãããæã£ã¦ãã¾ãã ããã`request`ã`session`ãªãã¸ã§ã¯ãã«ã¯ãå ¨ã¦ã®ãªã¯ã¨ã¹ãã«å¯¾ããåä¸ã®ã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹ãããã ããªã®ã§ãã¢ã¯ã»ã¹ã§ãã¾ããã `set`ã«ãã£ã¦ä½ããããªãã·ã§ã³ã¯ã¯ã©ã¹ã¬ãã«ã®ã¡ã½ããã§ãã ``` ruby class MyApp < Sinatra::Base # ã¢ããªã±ã¼ã·ã§ã³ã¹ã³ã¼ãã®ä¸ã ã! set :foo, 42 foo # => 42 get '/foo' do # ããã¢ããªã±ã¼ã·ã§ã³ã¹ã³ã¼ãã®ä¸ã«ããªãã! end end ``` 次ã®å ´æã§ã¯ã¢ããªã±ã¼ã·ã§ã³ã¹ã³ã¼ããã¤ã³ãã£ã³ã°ãæã¡ã¾ãã * ã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹æ¬ä½ * æ¡å¼µã«ãã£ã¦å®ç¾©ãããã¡ã½ãã * `helpers`ã«æ¸¡ãããããã㯠* `set`ã®å¤ã¨ãã¦ä½¿ãããProcã¾ãã¯ããã㯠* `Sinatra.new`ã«æ¸¡ãããããã㯠ãã®ã¹ã³ã¼ããªãã¸ã§ã¯ã(ã¯ã©ã¹)ã¯æ¬¡ã®ããã«å©ç¨ã§ãã¾ãã * configureãããã¯ã«æ¸¡ããããªãã¸ã§ã¯ãçµç±(`configure { |c| ... }`) * ãªã¯ã¨ã¹ãã¹ã³ã¼ãã®ä¸ã§ã®`settings` ### ãªã¯ã¨ã¹ã/ã¤ã³ã¹ã¿ã³ã¹ã®ã¹ã³ã¼ã ãã£ã¦ãããªã¯ã¨ã¹ããã¨ã«ãããªãã®ã¢ããªã±ã¼ã·ã§ã³ã¯ã©ã¹ã®æ°ããã¤ã³ã¹ã¿ã³ã¹ãä½æãããå ¨ã¦ã®ãã³ãã©ãããã¯ããã®ã¹ã³ã¼ãã§å®è¡ããã¾ãã ãã®ã¹ã³ã¼ãã®å å´ããã¯`request`ã`session`ãªãã¸ã§ã¯ãã«ã¢ã¯ã»ã¹ãããã¨ãã§ãã`erb`ã`haml`ã®ãããªã¬ã³ããªã³ã°ã¡ã½ãããå¼ã³åºããã¨ãã§ãã¾ãã ãªã¯ã¨ã¹ãã¹ã³ã¼ãã®å å´ããã¯ã`settings`ãã«ãã¼ã«ãã£ã¦ã¢ããªã±ã¼ã·ã§ã³ã¹ã³ã¼ãã«ã¢ã¯ã»ã¹ãããã¨ãã§ãã¾ãã ``` ruby class MyApp < Sinatra::Base # ã¢ããªã±ã¼ã·ã§ã³ã¹ã³ã¼ãã®ä¸ã ã! get '/define_route/:name' do # '/define_route/:name'ã®ããã®ãªã¯ã¨ã¹ãã¹ã³ã¼ã @value = 42 settings.get("/#{params['name']}") do # "/#{params['name']}"ã®ããã®ãªã¯ã¨ã¹ãã¹ã³ã¼ã @value # => nil (not the same request) end "ã«ã¼ãã£ã³ã°ãå®ç¾©ããã!" end end ``` 次ã®å ´æã§ã¯ãªã¯ã¨ã¹ãã¹ã³ã¼ããã¤ã³ãã£ã³ã°ãæã¡ã¾ãã * get/head/post/put/delete/options/patch/link/unlink ããã㯠* before/after ãã£ã«ã¿ * helper ã¡ã½ãã * ãã³ãã¬ã¼ã/ãã¥ã¼ ### ããªã²ã¼ãã¹ã³ã¼ã ããªã²ã¼ãã¹ã³ã¼ãã¯ãåã«ã¯ã©ã¹ã¹ã³ã¼ãã«ã¡ã½ããã転éãã¾ãã ããããªãããã¯ã©ã¹ã®ãã¤ã³ãã£ã³ã°ãæã£ã¦ããªããããã¯ã©ã¹ã¹ã³ã¼ãã¨å ¨ãåããµãã¾ããããããã§ã¯ããã¾ããã å§è²ããã¨æ示çã«ç¤ºãããã¡ã½ããã®ã¿ãå©ç¨å¯è½ã§ãããã¾ãã¯ã©ã¹ã¹ã³ã¼ãã¨å¤æ°/ç¶æ ãå ±æãããã¨ã¯ã§ãã¾ãã(注: ç°ãªã£ã`self`ãæã£ã¦ãã¾ã)ã `Sinatra::Delegator.delegate :method_name`ãå¼ã³åºããã¨ã«ãã£ã¦ããªã²ã¼ãããã¡ã½ãããæ示çã«è¿½å ãããã¨ãã§ãã¾ãã 次ã®å ´æã§ã¯ããªã²ã¼ãã¹ã³ã¼ããæã¡ã¾ãã * ãã`require "sinatra"`ãã¦ãããªãã°ããããã¬ãã«ãã¤ã³ãã£ã³ã° * `Sinatra::Delegator` mixinã§extendããããªãã¸ã§ã¯ã ã³ã¼ããã覧ãã ãã: ããã§ã¯ [Sinatra::Delegator mixin](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/base.rb#L1609-1633)ã¯[mainãªãã¸ã§ã¯ãã«extendããã¦ãã¾ã](https://github.com/sinatra/sinatra/blob/ca06364/lib/sinatra/main.rb#L28-30)ã ## ã³ãã³ãã©ã¤ã³ Sinatraã¢ããªã±ã¼ã·ã§ã³ã¯ç´æ¥å®è¡ã§ãã¾ãã ``` shell ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-o HOST] [-s HANDLER] ``` ãªãã·ã§ã³: ``` -h # ãã«ã -p # ãã¼ãæå®(ããã©ã«ãã¯4567) -o # ãã¹ãæå®(ããã©ã«ãã¯0.0.0.0) -e # ç°å¢ãæå® (ããã©ã«ãã¯development) -s # rackserver/handlerãæå® (ããã©ã«ãã¯thin) -x # mutex lockãä»ãã (ããã©ã«ãã¯off) ``` ## å¿ è¦ç°å¢ 次ã®Rubyãã¼ã¸ã§ã³ãå ¬å¼ã«ãµãã¼ãããã¦ãã¾ãã <dl> <dt>Ruby 1.8.7</dt> <dd> 1.8.7ã¯å®å ¨ã«ãµãã¼ãããã¦ãã¾ãããç¹ã«ããã§ãªããã°ãªããªãã¨ããçç±ããªãã®ã§ããã°ãã¢ããã°ã¬ã¼ãã¾ãã¯JRubyã¾ãã¯Rubiniusã¸ã®ç§»è¡ãè¦ãã¾ãã1.8.7ã®ãµãã¼ããSinatra 2.0ã®åã«çµãããã¨ã¯ãªãã§ããããRuby 1.8.6ã¯ãµãã¼ã対象å¤ã§ãã </dd> <dt>Ruby 1.9.2</dt> <dd> 1.9.2ã¯å®å ¨ã«ãµãã¼ãããã¦ãã¾ãã1.9.2p0ã¯ãSinatraãèµ·åããã¨ãã«ã»ã°ã¡ã³ããã©ã«ããå¼ãèµ·ãããã¨ãåãã£ã¦ããã®ã§ã使ããªãã§ãã ãããå ¬å¼ãªãµãã¼ãã¯ãå°ãªãã¨ãSinatra 1.5ã®ãªãªã¼ã¹ã¾ã§ã¯ç¶ãã¾ãã </dd> <dt>Ruby 1.9.3</dt> <dd> 1.9.3ã¯å®å ¨ã«ãµãã¼ããããã¦æ¨å¥¨ããã¦ãã¾ãã以åã®ãã¼ã¸ã§ã³ããã®1.9.3ã¸ã®ç§»è¡ã¯å ¨ã»ãã·ã§ã³ãç¡å¹ã«ããç¹ãè¦ãã¦ããã¦ãã ããã </dd> <dt>Ruby 2.0.0</dt> <dd> 2.0.0ã¯å®å ¨ã«ãµãã¼ããããã¦æ¨å¥¨ããã¦ãã¾ããç¾å¨ããã®å ¬å¼ãµãã¼ããçµäºããè¨ç»ã¯ããã¾ããã </dd> <dt>Rubinius</dt> <dd> Rubiniusã¯å ¬å¼ã«ãµãã¼ãããã¦ãã¾ã(Rubinius >= 2.x)ã <tt>gem install puma</tt>ãããã¨ãæ¨å¥¨ããã¦ãã¾ãã </dd> <dt>JRuby</dt> <dd> JRubyã®ææ°å®å®çãå ¬å¼ã«ãµãã¼ãããã¦ãã¾ããJRubyã§Cæ¡å¼µã使ããã¨ã¯æ¨å¥¨ããã¦ãã¾ããã <tt>gem install trinidad</tt>ãããã¨ãæ¨å¥¨ããã¦ãã¾ãã </dd> </dl> éçºãã¼ã ã¯å¸¸ã«ææ°ã¨ãªãRubyãã¼ã¸ã§ã³ã«æ³¨è¦ãã¦ãã¾ãã 次ã®Rubyå®è£ ã¯å ¬å¼ã«ã¯ãµãã¼ãããã¦ãã¾ããããSinatraãèµ·åããã¨å ±åããã¦ãã¾ãã * JRubyã¨Rubiniusã®å¤ããã¼ã¸ã§ã³ * Ruby Enterprise Edition * MacRuby, Maglev, IronRuby * Ruby 1.9.0ã¨1.9.1 (ãããã®ä½¿ç¨ã¯ãè¦ããã¾ãã) å ¬å¼ãµãã¼ããããªãã¨ããæå³ã¯ãåé¡ãããã ãã§èµ·ããããµãã¼ãããã¦ãããã©ãããã©ã¼ã ä¸ã§ã¯èµ·ããªãå ´åã«ãéçºãã¼ã ã¯ããã¯ãã¡ãå´ã®åé¡ã§ã¯ãªãã¨ã¿ãªãã¨ãããã¨ã§ãã éçºãã¼ã ã¯ã¾ããruby-head(ææ°ã¨ãªã2.1.0)ã«å¯¾ãCIãå®è¡ãã¦ãã¾ããããããä¸è²«ãã¦åãããã«ãªãã¾ã§ä½ãä¿è¨¼ãã¾ããã2.1.0ãå®å ¨ã«ãµãã¼ããããã°ãã®éãã§ã¯ããã¾ããã Sinatraã¯ãå©ç¨ããRubyå®è£ ããµãã¼ããã¦ãããªãã¬ã¼ãã£ã³ã°ã·ã¹ãã ä¸ãªãåä½ããã¯ãã§ãã MacRubyã使ãå ´åã¯ã`gem install control_tower`ãã¦ãã ããã Sinatraã¯ç¾å¨ãCardinalãSmallRubyãBlueRubyã¾ãã¯1.8.7以åã®ãã¼ã¸ã§ã³ã®Rubyä¸ã§ã¯åä½ãã¾ããã ## ææ°éçºç Sinatraã®ææ°éçºçã®ã³ã¼ãã使ãããå ´åã¯ããã¹ã¿ã¼ãã©ã³ãã«å¯¾ãã¦ã¢ããªã±ã¼ã·ã§ã³ãèµ°ããã¦æ§ãã¾ãããããç¨åº¦å®å®ãã¦ãã¾ããã¾ããé©å®ãã¬ãªãªã¼ã¹çgemãpushãã¦ããã®ã§ã ``` shell gem install sinatra --pre ``` ããã°ãææ°ã®æ©è½ã®ããã¤ããå©ç¨ã§ãã¾ãã ### Bundlerã使ãå ´å ææ°ã®Sinatraã§ã¢ããªã±ã¼ã·ã§ã³ãåä½ããããå ´åã«ã¯ã[Bundler](http://gembundler.com/)ã使ãã®ããè¦ãã®ããæ¹ã§ãã ã¾ããBundlerããªããã°ãããã¤ã³ã¹ãã¼ã«ãã¾ãã ``` shell gem install bundler ``` ããã¦ãããã¸ã§ã¯ãã®ãã£ã¬ã¯ããªã§ã`Gemfile`ãä½ãã¾ãã ```ruby source 'https://rubygems.org' gem 'sinatra', :github => "sinatra/sinatra" # ä»ã®ä¾åã©ã¤ãã©ãª gem 'haml' # Hamlã使ãå ´å gem 'activerecord', '~> 3.0' # ActiveRecord 3.xãå¿ è¦ããããã¾ãã ``` ãã¼ã: `Gemfile`ã«ã¢ããªã±ã¼ã·ã§ã³ã®ä¾åã©ã¤ãã©ãªã®ãã¹ã¦ã並ã¹ãå¿ è¦ãããã¾ããããããSinatraãç´æ¥ä¾åãããã®(Rackããã³Tile)ã¯Bundlerã«ãã£ã¦èªåçã«åãè¾¼ã¾ãã追å ããã¾ãã ããã§ã以ä¸ã®ããã«ãã¦ã¢ããªã±ã¼ã·ã§ã³ãèµ·åãããã¨ãã§ãã¾ãã ``` shell bundle exec ruby myapp.rb ``` ### ç´æ¥çµã¿è¾¼ãå ´å ãã¼ã«ã«ã«ã¯ãã¼ã³ãä½ã£ã¦ã`sinatra/lib`ãã£ã¬ã¯ããªã`$LOAD_PATH`ã«è¿½å ãã¦ã¢ããªã±ã¼ã·ã§ã³ãèµ·åãã¾ãã ``` shell cd myapp git clone git://github.com/sinatra/sinatra.git ruby -I sinatra/lib myapp.rb ``` 追ã£ã¦Sinatraã®ã½ã¼ã¹ãæ´æ°ããæ¹æ³ã ``` shell cd myapp/sinatra git pull ``` ### ã°ãã¼ãã«ç°å¢ã«ã¤ã³ã¹ãã¼ã«ããå ´å Sinatraã®gemãèªèº«ã§ãã«ããããã¨ãã§ãã¾ãã ``` shell git clone git://github.com/sinatra/sinatra.git cd sinatra rake sinatra.gemspec rake install ``` gemãã«ã¼ãã¨ãã¦ã¤ã³ã¹ãã¼ã«ããå ´åã¯ãæå¾ã®ã¹ãããã¯ãããªãã¾ãã ``` shell sudo rake install ``` ## ãã¼ã¸ã§ãã³ã°(Versioning) Sinatraã¯ã[Semantic Versioning](http://semver.org/)ã«ãããSemVerããã³SemVerTagã®ä¸¡æ¹ã«æºæ ãã¦ãã¾ãã ## åèæç® * [ããã¸ã§ã¯ããµã¤ã](http://sinatra.github.com/) - ããã¥ã¡ã³ãããã¥ã¼ã¹ãä»ã®ãªã½ã¼ã¹ã¸ã®ãªã³ã¯ãããã¾ãã * [ããã¸ã§ã¯ãã«åå (è²¢ç®)ãã](http://sinatra.github.com/contributing.html) - ãã°ã¬ãã¼ã ãããã®éä¿¡ããµãã¼ããªã© * [Issue tracker](http://github.com/sinatra/sinatra/issues) * [Twitter](http://twitter.com/sinatra) * [ã¡ã¼ãªã³ã°ãªã¹ã](http://groups.google.com/group/sinatrarb/topics) * http://freenode.netä¸ã®IRC: [#sinatra](irc://chat.freenode.net/#sinatra) * [Sinatra Book](https://github.com/sinatra/sinatra-book/) ã¯ãã¯ããã¯ããã¥ã¼ããªã¢ã« * [Sinatra Recipes](http://recipes.sinatrarb.com/) ã³ãã¥ããã£ã«ããã¬ã·ãé * http://rubydoc.infoä¸ã®APIããã¥ã¡ã³ã: [ææ°ç(latest release)ç¨](http://rubydoc.info/gems/sinatra)ã¾ãã¯[ç¾å¨ã®HEADç¨](http://rubydoc.info/github/sinatra/sinatra) * [CIãµã¼ã](http://travis-ci.org/sinatra/sinatra) * [Greenbear Laboratory Rackæ¥æ¬èªããã¥ã¢ã«](http://route477.net/w/RackReferenceJa.html)