These extensions let Sinatra automatically choose what template to render or action to perform depending on the request’s Accept header.
Example:
# Without Sinatra::RespondWith get '/' do data = { :name => 'example' } request.accept.each do |type| case type.to_s when 'text/html' halt haml(:index, :locals => data) when 'text/json' halt data.to_json when 'application/atom+xml' halt nokogiri(:'index.atom', :locals => data) when 'application/xml', 'text/xml' halt nokogiri(:'index.xml', :locals => data) when 'text/plain' halt 'just an example' end end error 406 end # With Sinatra::RespondWith get '/' do respond_with :index, :name => 'example' do |f| f.txt { 'just an example' } end end
Both helper methods respond_to and respond_with let you define custom handlers like the one above for text/plain. respond_with additionally takes a template name and/or an object to offer the following default behavior:
If a template name is given, search for a template called name.format.engine (index.xml.nokogiri in the above example).
If a template name is given, search for a templated called name.engine for engines known to result in the requested format (index.haml).
If a file extension associated with the mime type is known to Sinatra, and the object responds to to_extension, call that method and use the result (data.to_json).
Since methods are triggered based on client input, this can lead to security issues (but not as severe as those might appear in the first place: keep in mind that only known file extensions are used). You should limit the possible formats you serve.
This is possible with the provides condition:
get '/', :provides => [:html, :json, :xml, :atom] do respond_with :index, :name => 'example' end
However, since you have to set provides for every route, this extension adds an app global (class method) `respond_to`, that lets you define content types for all routes:
respond_to :html, :json, :xml, :atom get('/a') { respond_with :index, :name => 'a' } get('/b') { respond_with :index, :name => 'b' }
Use the on method for defining actions for custom types:
get '/' do respond_to do |f| f.xml { nokogiri :index } f.on('application/custom') { custom_action } f.on('text/*') { data.to_s } f.on('*/*') { "matches everything" } end end
Definition order does not matter.
# File lib/sinatra/respond_with.rb, line 194 def mime_type(*) result = super remap_extensions result end
# File lib/sinatra/respond_with.rb, line 187 def remap_extensions ext_map.clear Rack::Mime::MIME_TYPES.each { |e,t| ext_map[t] << e[1..-1].to_sym } ext_map['text/javascript'] << 'js' ext_map['text/xml'] << 'xml' end
Generated with the Darkfish Rdoc Generator 2.