diff --git a/CHANGES b/CHANGES index 0c6fd81043..55461bc33f 100644 --- a/CHANGES +++ b/CHANGES @@ -11,14 +11,23 @@ * Important: 1.8.6 support has been dropped. It is still usable if you use the backports gem, but no longer officially supported. (Konstantin Haase) - * It is now possible to use a different target class for the top level DLS (aka + * It is now possible to use a different target class for the top level DSL (aka classic style) than `Sinatra::Application` by setting `Delegator.target`. This was mainly introduced to ease testing. (Konstantin Haase) * Added `request.accept?` and `request.preferred_type` to ease dealing with `Accept` headers. (Konstantin Haase) -= 1.2.2 / Not Yet Released += 1.2.3 / 2011-04-13 + + * This release is compatible with Tilt 1.3, it will still work with Tilt 1.2.2, + however, if you want to use a newer Tilt version, you have to upgrade to at + least this version of Sinatra. (Konstantin Haase) + + * Helpers dealing with time, like `expires`, handle objects that pretend to be + numbers, like `ActiveSupport::Duration`, better. (Konstantin Haase) + += 1.2.2 / 2011-04-08 * The `:provides => :js` condition now matches both `application/javascript` and `text/javascript`. The `:provides => :xml` condition now matches both @@ -108,6 +117,10 @@ * Sinatra now ships with a Gemfile for development dependencies, since it eases supporting different platforms, like JRuby. (Konstantin Haase) += 1.1.4 / 2011-04-13 + + * Compatible with Tilt 1.3. (Konstantin Haase) + = 1.1.3 / 2011-02-20 * Fixed issues with `user_agent` condition if the user agent header is missing. diff --git a/Gemfile b/Gemfile index 8e67ef0b1f..46929454ce 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ # If you have issues with a gem: `bundle install --without-coffee-script`. RUBY_ENGINE = 'ruby' unless defined? RUBY_ENGINE +TILT_REPO = "git://github.com/rtomayko/tilt.git" source :rubygems unless ENV['QUICK'] gemspec @@ -14,6 +15,15 @@ gemspec gem 'rake' gem 'rack-test', '>= 0.5.6' +# Allows stuff like `tilt=1.2.2 bundle install` or `tilt=master ...`. +# Used by the CI. +tilt = ENV['tilt'].dup || 'stable' +tilt.sub! 'tilt-', '' +if tilt != 'stable' + tilt = {:git => TILT_REPO, :branch => tilt} unless tilt =~ /(\d+\.)+\d+/ + gem 'tilt', tilt +end + gem 'haml', '>= 3.0', :group => 'haml' gem 'builder', :group => 'builder' gem 'erubis', :group => 'erubis' @@ -39,5 +49,4 @@ platforms :mri_18 do # bundler platforms are broken next if RUBY_ENGINE != 'ruby' or RUBY_VERSION > "1.8" gem 'rcov', :group => 'rcov' - gem 'therubyracer', :group => 'coffee-script' end diff --git a/README.rdoc b/README.rdoc index 4d8dbf95a5..f29db905cd 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1882,4 +1882,7 @@ SemVerTag. * {Twitter}[http://twitter.com/sinatra] * {Mailing List}[http://groups.google.com/group/sinatrarb/topics] * {IRC: #sinatra}[irc://chat.freenode.net/#sinatra] on http://freenode.net +* API documentation for the {latest release}[http://rubydoc.info/gems/sinatra] + or the {current HEAD}[http://rubydoc.info/github/sinatra/sinatra] on + http://rubydoc.info/ diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index 6f91d74640..3b09a1c6ef 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -340,8 +340,8 @@ def cache_control(*values) def expires(amount, *values) values << {} unless values.last.kind_of?(Hash) - if Integer === amount - time = Time.now + amount + if amount.is_a? Integer + time = Time.now + amount.to_i max_age = amount else time = time_for amount @@ -405,7 +405,7 @@ def back def time_for(value) if value.respond_to? :to_time value.to_time - elsif Time === value + elsif value.is_a? Time value elsif value.respond_to? :new_offset # DateTime#to_time does the same on 1.9 @@ -415,13 +415,13 @@ def time_for(value) elsif value.respond_to? :mday # Date#to_time does the same on 1.9 Time.local(value.year, value.mon, value.mday) - elsif Numeric === value + elsif value.is_a? Numeric Time.at value else Time.parse value.to_s end rescue ArgumentError => boom - raise boom.to_s + raise boom rescue Exception raise ArgumentError, "unable to convert #{value.inspect} to a Time object" end @@ -523,8 +523,9 @@ def slim(template, options={}, locals={}) # Calls the given block for every possible template file in views, # named name.ext, where ext is registered on engine. def find_template(views, name, engine) - Tilt.mappings.each do |ext, klass| - next unless klass == engine + yield ::File.join(views, "#{name}.#{@preferred_extension}") + Tilt.mappings.each do |ext, engines| + next unless ext != @preferred_extension and Array(engines).include? engine yield ::File.join(views, "#{name}.#{ext}") end end @@ -585,6 +586,7 @@ def compile_template(engine, data, options, views) template.new(path, line.to_i, options) { body } else found = false + @preferred_extension = engine.to_s find_template(views, data, template) do |file| path ||= file # keep the initial path rather than the last one if found = File.exists?(file) diff --git a/sinatra.gemspec b/sinatra.gemspec index c0712dd8b4..074ea357b5 100644 --- a/sinatra.gemspec +++ b/sinatra.gemspec @@ -123,10 +123,9 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w[README.rdoc README.de.rdoc README.jp.rdoc README.fr.rdoc README.es.rdoc README.hu.rdoc README.zh.rdoc LICENSE] s.add_dependency 'rack', '~> 1.2' - s.add_dependency 'tilt', '>= 1.2.2', '< 2.0' + s.add_dependency 'tilt', '~> 1.2', '>= 1.2.2' s.add_development_dependency 'shotgun', '~> 0.6' - s.has_rdoc = true s.homepage = "http://sinatra.rubyforge.org" s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"] s.require_paths = %w[lib] diff --git a/test/coffee_test.rb b/test/coffee_test.rb index 918139b4ba..c8c84429b5 100644 --- a/test/coffee_test.rb +++ b/test/coffee_test.rb @@ -2,6 +2,13 @@ begin require 'coffee-script' +require 'execjs' + +begin + ExecJS.compile '1' +rescue Exception + raise LoadError, 'unable to execute JavaScript' +end class CoffeeTest < Test::Unit::TestCase def coffee_app(options = {}, &block) @@ -16,7 +23,7 @@ def coffee_app(options = {}, &block) it 'renders inline Coffee strings' do coffee_app { coffee "alert 'Aye!'\n" } assert ok? - assert_equal "(function() {\n alert('Aye!');\n}).call(this);\n", body + assert body.include?("alert('Aye!');") end it 'defaults content type to javascript' do @@ -45,13 +52,13 @@ def coffee_app(options = {}, &block) it 'renders .coffee files in views path' do coffee_app { coffee :hello } assert ok? - assert_equal "(function() {\n alert(\"Aye!\");\n}).call(this);\n", body + assert_include body, "alert(\"Aye!\");" end it 'ignores the layout option' do coffee_app { coffee :hello, :layout => :layout2 } assert ok? - assert_equal "(function() {\n alert(\"Aye!\");\n}).call(this);\n", body + assert_include body, "alert(\"Aye!\");" end it "raises error if template not found" do @@ -62,21 +69,18 @@ def coffee_app(options = {}, &block) end it "passes coffee options to the coffee engine" do - coffee_app { - coffee "alert 'Aye!'\n", - :no_wrap => true - } + coffee_app { coffee "alert 'Aye!'\n", :no_wrap => true } assert ok? assert_equal "alert('Aye!');", body end it "passes default coffee options to the coffee engine" do - mock_app { + mock_app do set :coffee, :no_wrap => true # default coffee style is :nested get '/' do coffee "alert 'Aye!'\n" end - } + end get '/' assert ok? assert_equal "alert('Aye!');", body diff --git a/test/helper.rb b/test/helper.rb index b75b03012b..99ec82454a 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -65,6 +65,10 @@ def assert_body(value) assert_equal value.lstrip.gsub(/\s*\n\s*/, ""), body.lstrip.gsub(/\s*\n\s*/, "") end + def assert_include(str, substr) + assert str.include?(substr), "expected #{str.inspect} to include #{substr.inspect}" + end + # Delegate other missing methods to response. def method_missing(name, *args, &block) if response && response.respond_to?(name) diff --git a/test/helpers_test.rb b/test/helpers_test.rb index f20bf2cea8..352763e5cd 100644 --- a/test/helpers_test.rb +++ b/test/helpers_test.rb @@ -638,6 +638,18 @@ def send_file_app(opts={}) get '/baz' do expires Time.at(0) end + + get '/blah' do + obj = Object.new + def obj.method_missing(*a, &b) 60.send(*a, &b) end + def obj.is_a?(thing) 60.is_a?(thing) end + expires obj, :public, :no_cache + 'Hello World' + end + + get '/boom' do + expires '1000' + end end end @@ -660,6 +672,15 @@ def send_file_app(opts={}) get '/baz' assert_equal 'Thu, 01 Jan 1970 00:00:00 GMT', response['Expires'] end + + it 'accepts values pretending to be a Numeric (like ActiveSupport::Duration)' do + get '/blah' + assert_equal ['public', 'no-cache', 'max-age=60'], response['Cache-Control'].split(', ') + end + + it 'fails when Time.parse raises an ArgumentError' do + assert_raise(ArgumentError) { get '/boom' } + end end describe 'last_modified' do