commit 117cc667884f97677def7faff84ad7e991ca1b47 Author: Nicolas Sanguinetti Date: Thu May 7 02:58:50 2009 -0300 Initial commit diff --git a/sinatra-contrib/LICENSE b/sinatra-contrib/LICENSE new file mode 100644 index 00000000..3eb6c2f4 --- /dev/null +++ b/sinatra-contrib/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2008-2009 Nicolas Sanguinetti, entp.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/sinatra-contrib/README.rdoc b/sinatra-contrib/README.rdoc new file mode 100644 index 00000000..12022a7b --- /dev/null +++ b/sinatra-contrib/README.rdoc @@ -0,0 +1,41 @@ += ContentFor + +Small extension for the Sinatra[http://sinatrarb.com] web framework +that allows you to use the following helpers in your views: + + <% content_for :some_key do %> + ... + <% end %> + + <% yield_content :some_key %> + +This allows you to capture blocks inside views to be rendered later +in this request. For example, to populate different parts of your +layout from your view. + +== Usage + +If you're writing "classic" style apps, then requring +sinatra/content_for should be enough. If you're writing +"classy" apps, then you also need to call +helpers Sinatra::ContentFor in your app definition. + +== And how is this useful? + +For example, some of your views might need a few javascript tags and +stylesheets, but you don't want to force this files in all your pages. +Then you can put <% yield_content :scripts_and_styles %> on +your layout, inside the tag, and each view can call +content_for setting the appropriate set of tags that should +be added to the layout. + +== Warning + +This only works with ERB as a rendering mechanism. I haven't figured +how to make it work with Haml. If you find a way, contact me and I'll +include it. + +== Credits + +Code by foca[http://github.com/foca], inspired on the Ruby on Rails +helpers with the same name. diff --git a/sinatra-contrib/lib/sinatra/content_for.rb b/sinatra-contrib/lib/sinatra/content_for.rb new file mode 100644 index 00000000..921e06eb --- /dev/null +++ b/sinatra-contrib/lib/sinatra/content_for.rb @@ -0,0 +1,19 @@ +module Sinatra + module ContentFor + def content_for(key, &block) + content_blocks[key.to_sym] << block + end + + def yield_content(key) + content_blocks[key.to_sym].map {|content| content.call }.join("") + end + + private + + def content_blocks + @content_blocks ||= Hash.new {|h,k| h[k] = [] } + end + end + + helpers ContentFor +end diff --git a/sinatra-contrib/test/content_for_test.rb b/sinatra-contrib/test/content_for_test.rb new file mode 100644 index 00000000..088129d6 --- /dev/null +++ b/sinatra-contrib/test/content_for_test.rb @@ -0,0 +1,72 @@ +ENV['RACK_ENV'] = 'test' + +begin + require 'rack' +rescue LoadError + require 'rubygems' + require 'rack' +end + +require 'contest' +require 'sinatra/test' + +require File.dirname(__FILE__) + '/../lib/sinatra/content_for' + +Sinatra::Base.set :environment, :test + +module Sinatra + class Base + set :environment, :test + helpers ContentFor + end +end + +class Test::Unit::TestCase + include Sinatra::Test + + class << self + alias_method :it, :test + end + + def mock_app(base=Sinatra::Base, &block) + @app = Sinatra.new(base, &block) + end +end + +class ContentForTest < Test::Unit::TestCase + def erb_app(view) + mock_app { + layout { '<% yield_content :foo %>' } + get('/') { erb view } + } + end + + it 'renders blocks declared with the same key you use when rendering' do + erb_app '<% content_for :foo do %>foo<% end %>' + + get '/' + assert ok? + assert_equal 'foo', body + end + + it 'does not render a block with a different key' do + erb_app '<% content_for :bar do %>bar<% end %>' + + get '/' + assert ok? + assert_equal '', body + end + + it 'renders multiple blocks with the same key' do + erb_app <<-erb_snippet + <% content_for :foo do %>foo<% end %> + <% content_for :foo do %>bar<% end %> + <% content_for :baz do %>WON'T RENDER ME<% end %> + <% content_for :foo do %>baz<% end %> + erb_snippet + + get '/' + assert ok? + assert_equal 'foobarbaz', body + end +end