diff options
28 files changed, 448 insertions, 329 deletions
@@ -11,6 +11,7 @@ end gem 'rack-test', github: "brynary/rack-test" gem 'bcrypt-ruby', '~> 3.0.0' gem 'jquery-rails' +gem 'minitest', '~> 3.0.0' if ENV['JOURNEY'] gem 'journey', path: ENV['JOURNEY'] diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb index 95c588c00a..3e2a9e232d 100644 --- a/actionpack/lib/action_dispatch/routing/redirection.rb +++ b/actionpack/lib/action_dispatch/routing/redirection.rb @@ -35,6 +35,10 @@ module ActionDispatch def path(params, request) block.call params, request end + + def inspect + "Redirect (#{status})" + end end class OptionRedirect < Redirect # :nodoc: diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb index 62455b97f9..dfc26acfad 100644 --- a/actionpack/lib/action_view/helpers/number_helper.rb +++ b/actionpack/lib/action_view/helpers/number_helper.rb @@ -254,7 +254,7 @@ module ActionView parts = number.to_s.to_str.split('.') parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}") - parts.join(options[:separator]).html_safe + safe_join(parts, options[:separator]) end # Formats a +number+ with the specified level of diff --git a/actionpack/test/template/benchmark_helper_test.rb b/actionpack/test/template/benchmark_helper_test.rb index 1bdda22959..8c198d2562 100644 --- a/actionpack/test/template/benchmark_helper_test.rb +++ b/actionpack/test/template/benchmark_helper_test.rb @@ -19,6 +19,6 @@ class BenchmarkHelperTest < ActionView::TestCase log = StringIO.new self.stubs(:logger).returns(Logger.new(log)) benchmark {} - assert_match(log.rewind && log.read, /Benchmarking \(\d+.\d+ms\)/) + assert_match(/Benchmarking \(\d+.\d+ms\)/, log.rewind && log.read) end end diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 5c6f23d70b..14ca6d9879 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -78,6 +78,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal '12,345,678-05', number_with_delimiter(12345678.05, :separator => '-') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :separator => ',', :delimiter => '.') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :delimiter => '.', :separator => ',') + assert_equal '1<script></script>01', number_with_delimiter(1.01, :separator => "<script></script>") + assert_equal '1<script></script>000', number_with_delimiter(1000, :delimiter => "<script></script>") end def test_number_with_precision diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 11fd0e7047..8f1f315e42 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,10 +1,64 @@ ## Rails 4.0.0 (unreleased) ## +* Deprecated most of the 'dynamic finder' methods. All dynamic methods + except for `find_by_...` and `find_by_...!` are deprecated. Here's + how you can rewrite the code: + + * `find_all_by_...` can be rewritten using `where(...)` + * `find_last_by_...` can be rewritten using `where(...).last` + * `scoped_by_...` can be rewritten using `where(...)` + * `find_or_initialize_by_...` can be rewritten using + `where(...).first_or_initialize` + * `find_or_create_by_...` can be rewritten using + `where(...).first_or_create` + * `find_or_create_by_...!` can be rewritten using + `where(...).first_or_create!` + + The implementation of the deprecated dynamic finders has been moved + to the `active_record_deprecated_finders` gem. See below for details. + + *Jon Leighton* + +* Deprecated the old-style hash based finder API. This means that + methods which previously accepted "finder options" no longer do. For + example this: + + Post.find(:all, :conditions => { :comments_count => 10 }, :limit => 5) + + Should be rewritten in the new style which has existed since Rails 3: + + Post.where(comments_count: 10).limit(5) + + Note that as an interim step, it is possible to rewrite the above as: + + Post.scoped(:where => { :comments_count => 10 }, :limit => 5) + + This could save you a lot of work if there is a lot of old-style + finder usage in your application. + + Calling `Post.scoped(options)` is a shortcut for + `Post.scoped.merge(options)`. `Relation#merge` now accepts a hash of + options, but they must be identical to the names of the equivalent + finder method. These are mostly identical to the old-style finder + option names, except in the following cases: + + * `:conditions` becomes `:where` + * `:include` becomes `:includes` + * `:extend` becomes `:extending` + + The code to implement the deprecated features has been moved out to + the `active_record_deprecated_finders` gem. This gem is a dependency + of Active Record in Rails 4.0. It will no longer be a dependency + from Rails 4.1, but if your app relies on the deprecated features + then you can add it to your own Gemfile. It will be maintained by + the Rails core team until Rails 5.0 is released. + + *Jon Leighton* + * It's not possible anymore to destroy a model marked as read only. *Johannes Barre* - * Added ability to ActiveRecord::Relation#from to accept other ActiveRecord::Relation objects Record.from(subquery) diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index 0b634ab944..30fc44b4c2 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -18,7 +18,7 @@ module ActiveRecord::Associations::Builder model.send(:include, Module.new { class_eval <<-RUBY, __FILE__, __LINE__ + 1 def destroy_associations - association(#{name.to_sym.inspect}).delete_all_on_destroy + association(#{name.to_sym.inspect}).delete_all super end RUBY diff --git a/activerecord/lib/active_record/associations/builder/has_many.rb b/activerecord/lib/active_record/associations/builder/has_many.rb index 9ddfd433e4..d37d4e9d33 100644 --- a/activerecord/lib/active_record/associations/builder/has_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_many.rb @@ -42,7 +42,7 @@ module ActiveRecord::Associations::Builder def define_delete_all_dependency_method name = self.name mixin.redefine_method(dependency_method_name) do - association(name).delete_all_on_destroy + association(name).delete_all end end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 3af5ff3eab..c6c7cdc188 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -146,19 +146,12 @@ module ActiveRecord # # See delete for more info. def delete_all - delete(load_target).tap do + delete(:all).tap do reset loaded! end end - # Called when the association is declared as :dependent => :delete_all. This is - # an optimised version which avoids loading the records into memory. Not really - # for public consumption. - def delete_all_on_destroy - scoped.delete_all - end - # Destroy all the records from this association. # # See destroy for more info. @@ -218,7 +211,17 @@ module ActiveRecord # are actually removed from the database, that depends precisely on # +delete_records+. They are in any case removed from the collection. def delete(*records) - delete_or_destroy(records, options[:dependent]) + dependent = options[:dependent] + + if records.first == :all + if loaded? || dependent == :destroy + delete_or_destroy(load_target, dependent) + else + delete_records(:all, dependent) + end + else + delete_or_destroy(records, dependent) + end end # Destroy +records+ and remove them from this association calling diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index a4cea99372..58d041ec1d 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -32,10 +32,6 @@ module ActiveRecord record end - # ActiveRecord::Relation#delete_all needs to support joins before we can use a - # SQL-only implementation. - alias delete_all_on_destroy delete_all - private def count_records @@ -44,13 +40,20 @@ module ActiveRecord def delete_records(records, method) if sql = options[:delete_sql] + records = load_target if records == :all records.each { |record| owner.connection.delete(interpolate(sql, record)) } else - relation = join_table - stmt = relation.where(relation[reflection.foreign_key].eq(owner.id). - and(relation[reflection.association_foreign_key].in(records.map { |x| x.id }.compact)) - ).compile_delete - owner.connection.delete stmt + relation = join_table + condition = relation[reflection.foreign_key].eq(owner.id) + + unless records == :all + condition = condition.and( + relation[reflection.association_foreign_key] + .in(records.map { |x| x.id }.compact) + ) + end + + owner.connection.delete(relation.where(condition).compile_delete) end end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 059e6c77bc..e631579087 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -89,8 +89,12 @@ module ActiveRecord records.each { |r| r.destroy } update_counter(-records.length) unless inverse_updates_counter_cache? else - keys = records.map { |r| r[reflection.association_primary_key] } - scope = scoped.where(reflection.association_primary_key => keys) + if records == :all + scope = scoped + else + keys = records.map { |r| r[reflection.association_primary_key] } + scope = scoped.where(reflection.association_primary_key => keys) + end if method == :delete_all update_counter(-scope.delete_all) diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 53d49fef2e..2683aaf5da 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -54,10 +54,6 @@ module ActiveRecord record end - # ActiveRecord::Relation#delete_all needs to support joins before we can use a - # SQL-only implementation. - alias delete_all_on_destroy delete_all - private def through_association @@ -126,7 +122,12 @@ module ActiveRecord def delete_records(records, method) ensure_not_nested - scope = through_association.scoped.where(construct_join_attributes(*records)) + # This is unoptimised; it will load all the target records + # even when we just want to delete everything. + records = load_target if records == :all + + scope = through_association.scoped + scope.where! construct_join_attributes(*records) case method when :destroy diff --git a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb index b9b5ec7956..b1a0f83b5f 100644 --- a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb @@ -12,10 +12,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration def up <% attributes.each do |attribute| -%> <%- if migration_action -%> - <%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><%= attribute.inject_options %><% end %> - <%- if attribute.has_index? && migration_action == 'add' -%> - add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> - <%- end -%> + <%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %> <%- end -%> <%- end -%> end @@ -23,8 +20,8 @@ class <%= migration_class_name %> < ActiveRecord::Migration def down <% attributes.reverse.each do |attribute| -%> <%- if migration_action -%> - <%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><%= attribute.inject_options %><% end %> - <%- if attribute.has_index? && migration_action == 'remove' -%> + add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> + <%- if attribute.has_index? -%> add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> <%- end -%> <%- end -%> diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 0e361456f0..ed1caa2ef5 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -380,6 +380,12 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_equal 0, active_record.developers_by_sql(true).size end + def test_deleting_all_with_sql + project = Project.find(1) + project.developers_by_sql.delete_all + assert_equal 0, project.developers_by_sql.size + end + def test_deleting_all david = Developer.find(1) david.projects.reload diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 5bd7ed5a1b..b51f4b0786 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1614,4 +1614,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [client], firm.clients_of_firm assert_equal [client], firm.reload.clients_of_firm end + + test "delete_all, when not loaded, doesn't load the records" do + post = posts(:welcome) + + assert post.taggings_with_delete_all.count > 0 + assert !post.taggings_with_delete_all.loaded? + + # 2 queries: one DELETE and another to update the counter cache + assert_queries(2) do + post.taggings_with_delete_all.delete_all + end + end end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 20279f814b..37fa13f771 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -2,6 +2,7 @@ require File.expand_path('../../../../load_paths', __FILE__) require 'config' +gem 'minitest' require 'minitest/autorun' require 'stringio' require 'mocha' diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb new file mode 100644 index 0000000000..063209389f --- /dev/null +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -0,0 +1,221 @@ +require "cases/migration/helper" + +module ActiveRecord + class Migration + class TableTest < ActiveRecord::TestCase + class MockConnection < MiniTest::Mock + def native_database_types + { + :string => 'varchar(255)', + :integer => 'integer', + } + end + + def type_to_sql(type, limit, precision, scale) + native_database_types[type] + end + end + + def setup + @connection = MockConnection.new + end + + def teardown + assert @connection.verify + end + + def with_change_table + yield ConnectionAdapters::Table.new(:delete_me, @connection) + end + + def test_references_column_type_adds_id + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, 'customer_id', :integer, {}] + t.references :customer + end + end + + def test_remove_references_column_type_removes_id + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, 'customer_id'] + t.remove_references :customer + end + end + + def test_add_belongs_to_works_like_add_references + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, 'customer_id', :integer, {}] + t.belongs_to :customer + end + end + + def test_remove_belongs_to_works_like_remove_references + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, 'customer_id'] + t.remove_belongs_to :customer + end + end + + def test_references_column_type_with_polymorphic_adds_type + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, 'taggable_id', :integer, {}] + @connection.expect :add_column, nil, [:delete_me, 'taggable_type', :string, {}] + t.references :taggable, :polymorphic => true + end + end + + def test_remove_references_column_type_with_polymorphic_removes_type + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, 'taggable_id'] + @connection.expect :remove_column, nil, [:delete_me, 'taggable_type'] + t.remove_references :taggable, :polymorphic => true + end + end + + def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, 'taggable_id', :integer, {:null => false}] + @connection.expect :add_column, nil, [:delete_me, 'taggable_type', :string, {:null => false}] + t.references :taggable, :polymorphic => true, :null => false + end + end + + def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, 'taggable_id'] + @connection.expect :remove_column, nil, [:delete_me, 'taggable_type'] + t.remove_references :taggable, :polymorphic => true, :null => false + end + end + + def test_timestamps_creates_updated_at_and_created_at + with_change_table do |t| + @connection.expect :add_timestamps, nil, [:delete_me] + t.timestamps + end + end + + def test_remove_timestamps_creates_updated_at_and_created_at + with_change_table do |t| + @connection.expect :remove_timestamps, nil, [:delete_me] + t.remove_timestamps + end + end + + def string_column + @connection.native_database_types[:string] + end + + def integer_column + @connection.native_database_types[:integer] + end + + def test_integer_creates_integer_column + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, :foo, integer_column, {}] + @connection.expect :add_column, nil, [:delete_me, :bar, integer_column, {}] + t.integer :foo, :bar + end + end + + def test_string_creates_string_column + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, :foo, string_column, {}] + @connection.expect :add_column, nil, [:delete_me, :bar, string_column, {}] + t.string :foo, :bar + end + end + + def test_column_creates_column + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, :bar, :integer, {}] + t.column :bar, :integer + end + end + + def test_column_creates_column_with_options + with_change_table do |t| + @connection.expect :add_column, nil, [:delete_me, :bar, :integer, {:null => false}] + t.column :bar, :integer, :null => false + end + end + + def test_index_creates_index + with_change_table do |t| + @connection.expect :add_index, nil, [:delete_me, :bar, {}] + t.index :bar + end + end + + def test_index_creates_index_with_options + with_change_table do |t| + @connection.expect :add_index, nil, [:delete_me, :bar, {:unique => true}] + t.index :bar, :unique => true + end + end + + def test_index_exists + with_change_table do |t| + @connection.expect :index_exists?, nil, [:delete_me, :bar, {}] + t.index_exists?(:bar) + end + end + + def test_index_exists_with_options + with_change_table do |t| + @connection.expect :index_exists?, nil, [:delete_me, :bar, {:unique => true}] + t.index_exists?(:bar, :unique => true) + end + end + + def test_change_changes_column + with_change_table do |t| + @connection.expect :change_column, nil, [:delete_me, :bar, :string, {}] + t.change :bar, :string + end + end + + def test_change_changes_column_with_options + with_change_table do |t| + @connection.expect :change_column, nil, [:delete_me, :bar, :string, {:null => true}] + t.change :bar, :string, :null => true + end + end + + def test_change_default_changes_column + with_change_table do |t| + @connection.expect :change_column_default, nil, [:delete_me, :bar, :string] + t.change_default :bar, :string + end + end + + def test_remove_drops_single_column + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, :bar] + t.remove :bar + end + end + + def test_remove_drops_multiple_columns + with_change_table do |t| + @connection.expect :remove_column, nil, [:delete_me, :bar, :baz] + t.remove :bar, :baz + end + end + + def test_remove_index_removes_index_with_options + with_change_table do |t| + @connection.expect :remove_index, nil, [:delete_me, {:unique => true}] + t.remove_index :unique => true + end + end + + def test_rename_renames_column + with_change_table do |t| + @connection.expect :rename_column, nil, [:delete_me, :bar, :baz] + t.rename :bar, :baz + end + end + end + end +end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index cad93936c9..5d1bad0d54 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -421,228 +421,6 @@ class ReservedWordsMigrationTest < ActiveRecord::TestCase end end - -class ChangeTableMigrationsTest < ActiveRecord::TestCase - def setup - @connection = Person.connection - @connection.stubs(:add_index) - @connection.create_table :delete_me, :force => true do |t| - end - end - - def teardown - Person.connection.drop_table :delete_me rescue nil - end - - def test_references_column_type_adds_id - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) - t.references :customer - end - end - - def test_remove_references_column_type_removes_id - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'customer_id') - t.remove_references :customer - end - end - - def test_add_belongs_to_works_like_add_references - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'customer_id', :integer, {}) - t.belongs_to :customer - end - end - - def test_remove_belongs_to_works_like_remove_references - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'customer_id') - t.remove_belongs_to :customer - end - end - - def test_references_column_type_with_polymorphic_adds_type - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {}) - @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {}) - t.references :taggable, :polymorphic => true - end - end - - def test_remove_references_column_type_with_polymorphic_removes_type - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'taggable_type') - @connection.expects(:remove_column).with(:delete_me, 'taggable_id') - t.remove_references :taggable, :polymorphic => true - end - end - - def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, 'taggable_type', :string, {:null => false}) - @connection.expects(:add_column).with(:delete_me, 'taggable_id', :integer, {:null => false}) - t.references :taggable, :polymorphic => true, :null => false - end - end - - def test_remove_references_column_type_with_polymorphic_and_options_null_is_false_removes_table_flag - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, 'taggable_type') - @connection.expects(:remove_column).with(:delete_me, 'taggable_id') - t.remove_references :taggable, :polymorphic => true, :null => false - end - end - - def test_timestamps_creates_updated_at_and_created_at - with_change_table do |t| - @connection.expects(:add_timestamps).with(:delete_me) - t.timestamps - end - end - - def test_remove_timestamps_creates_updated_at_and_created_at - with_change_table do |t| - @connection.expects(:remove_timestamps).with(:delete_me) - t.remove_timestamps - end - end - - def string_column - if current_adapter?(:PostgreSQLAdapter) - "character varying(255)" - elsif current_adapter?(:OracleAdapter) - 'VARCHAR2(255)' - else - 'varchar(255)' - end - end - - def integer_column - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - 'int(11)' - elsif current_adapter?(:OracleAdapter) - 'NUMBER(38)' - else - 'integer' - end - end - - def test_integer_creates_integer_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :foo, integer_column, {}) - @connection.expects(:add_column).with(:delete_me, :bar, integer_column, {}) - t.integer :foo, :bar - end - end - - def test_string_creates_string_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :foo, string_column, {}) - @connection.expects(:add_column).with(:delete_me, :bar, string_column, {}) - t.string :foo, :bar - end - end - - def test_column_creates_column - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :bar, :integer, {}) - t.column :bar, :integer - end - end - - def test_column_creates_column_with_options - with_change_table do |t| - @connection.expects(:add_column).with(:delete_me, :bar, :integer, {:null => false}) - t.column :bar, :integer, :null => false - end - end - - def test_index_creates_index - with_change_table do |t| - @connection.expects(:add_index).with(:delete_me, :bar, {}) - t.index :bar - end - end - - def test_index_creates_index_with_options - with_change_table do |t| - @connection.expects(:add_index).with(:delete_me, :bar, {:unique => true}) - t.index :bar, :unique => true - end - end - - def test_index_exists - with_change_table do |t| - @connection.expects(:index_exists?).with(:delete_me, :bar, {}) - t.index_exists?(:bar) - end - end - - def test_index_exists_with_options - with_change_table do |t| - @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true}) - t.index_exists?(:bar, :unique => true) - end - end - - def test_change_changes_column - with_change_table do |t| - @connection.expects(:change_column).with(:delete_me, :bar, :string, {}) - t.change :bar, :string - end - end - - def test_change_changes_column_with_options - with_change_table do |t| - @connection.expects(:change_column).with(:delete_me, :bar, :string, {:null => true}) - t.change :bar, :string, :null => true - end - end - - def test_change_default_changes_column - with_change_table do |t| - @connection.expects(:change_column_default).with(:delete_me, :bar, :string) - t.change_default :bar, :string - end - end - - def test_remove_drops_single_column - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, :bar) - t.remove :bar - end - end - - def test_remove_drops_multiple_columns - with_change_table do |t| - @connection.expects(:remove_column).with(:delete_me, :bar, :baz) - t.remove :bar, :baz - end - end - - def test_remove_index_removes_index_with_options - with_change_table do |t| - @connection.expects(:remove_index).with(:delete_me, {:unique => true}) - t.remove_index :unique => true - end - end - - def test_rename_renames_column - with_change_table do |t| - @connection.expects(:rename_column).with(:delete_me, :bar, :baz) - t.rename :bar, :baz - end - end - - protected - def with_change_table - Person.connection.change_table :delete_me do |t| - yield t - end - end -end - if ActiveRecord::Base.connection.supports_bulk_alter? class BulkAlterTableMigrationsTest < ActiveRecord::TestCase def setup diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index f98d5b3777..5226ff0cbe 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -151,9 +151,7 @@ module ActiveSupport #:nodoc: end def %(args) - args = Array(args) - - args.map! do |arg| + args = Array(args).map do |arg| if !html_safe? || arg.html_safe? arg else diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index a0f610d60c..92b8417150 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -253,7 +253,7 @@ class Time :hour => 23, :min => 59, :sec => 59, - :usec => 999999.999 + :usec => Rational(999999999, 1000) ) end @@ -268,7 +268,7 @@ class Time change( :min => 59, :sec => 59, - :usec => 999999.999 + :usec => Rational(999999999, 1000) ) end @@ -288,7 +288,7 @@ class Time :hour => 23, :min => 59, :sec => 59, - :usec => 999999.999 + :usec => Rational(999999999, 1000) ) end alias :at_end_of_month :end_of_month @@ -321,7 +321,7 @@ class Time :hour => 23, :min => 59, :sec => 59, - :usec => 999999.999 + :usec => Rational(999999999, 1000) ) end alias :at_end_of_year :end_of_year diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index ec6986654e..2bea0f991a 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -196,6 +196,7 @@ module ActiveSupport class Base include ActionView::Helpers::NumberHelper + include ActionView::Helpers::OutputSafetyHelper attr_reader :total diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 67ac1b6ccd..451520ac5c 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -317,8 +317,7 @@ module ActiveSupport # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+. def method_missing(sym, *args, &block) - result = time.__send__(sym, *args, &block) - result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result + wrap_with_time_zone time.__send__(sym, *args, &block) end private @@ -336,11 +335,21 @@ module ActiveSupport end def transfer_time_values_to_utc_constructor(time) - ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:usec) ? time.usec : 0) + ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:nsec) ? Rational(time.nsec, 1000) : 0) end def duration_of_variable_length?(obj) ActiveSupport::Duration === obj && obj.parts.any? {|p| p[0].in?([:years, :months, :days]) } end + + def wrap_with_time_zone(time) + if time.acts_like?(:time) + self.class.new(nil, time_zone, time) + elsif time.is_a?(Range) + wrap_with_time_zone(time.begin)..wrap_with_time_zone(time.end) + else + time + end + end end end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 760d138623..e14a137f84 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -374,14 +374,14 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end def test_end_of_day - assert_equal Time.local(2005,2,21,23,59,59,999999.999), Date.new(2005,2,21).end_of_day + assert_equal Time.local(2005,2,21,23,59,59,Rational(999999999, 1000)), Date.new(2005,2,21).end_of_day end def test_end_of_day_when_zone_is_set zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'UTC' do with_tz_default zone do - assert_equal zone.local(2005,2,21,23,59,59,999999.999), Date.new(2005,2,21).end_of_day + assert_equal zone.local(2005,2,21,23,59,59,Rational(999999999, 1000)), Date.new(2005,2,21).end_of_day assert_equal zone, Date.new(2005,2,21).end_of_day.time_zone end end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index eee2caa60e..8437ef1347 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -463,6 +463,13 @@ class OutputSafetyTest < ActiveSupport::TestCase assert @other_string.html_safe? end + test "Concatting with % doesn't modify a string" do + @other_string = ["<p>", "<b>", "<h1>"] + _ = "%s %s %s".html_safe % @other_string + + assert_equal ["<p>", "<b>", "<h1>"], @other_string + end + test "Concatting a fixnum to safe always yields safe" do string = @string.html_safe string = string.concat(13) diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 4c1ed4b1ae..8bf3e6e7ae 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -109,49 +109,49 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_end_of_day - assert_equal Time.local(2007,8,12,23,59,59,999999.999), Time.local(2007,8,12,10,10,10).end_of_day + assert_equal Time.local(2007,8,12,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,12,10,10,10).end_of_day with_env_tz 'US/Eastern' do - assert_equal Time.local(2007,4,2,23,59,59,999999.999), Time.local(2007,4,2,10,10,10).end_of_day, 'start DST' - assert_equal Time.local(2007,10,29,23,59,59,999999.999), Time.local(2007,10,29,10,10,10).end_of_day, 'ends DST' + assert_equal Time.local(2007,4,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,4,2,10,10,10).end_of_day, 'start DST' + assert_equal Time.local(2007,10,29,23,59,59,Rational(999999999, 1000)), Time.local(2007,10,29,10,10,10).end_of_day, 'ends DST' end with_env_tz 'NZ' do - assert_equal Time.local(2006,3,19,23,59,59,999999.999), Time.local(2006,3,19,10,10,10).end_of_day, 'ends DST' - assert_equal Time.local(2006,10,1,23,59,59,999999.999), Time.local(2006,10,1,10,10,10).end_of_day, 'start DST' + assert_equal Time.local(2006,3,19,23,59,59,Rational(999999999, 1000)), Time.local(2006,3,19,10,10,10).end_of_day, 'ends DST' + assert_equal Time.local(2006,10,1,23,59,59,Rational(999999999, 1000)), Time.local(2006,10,1,10,10,10).end_of_day, 'start DST' end end def test_end_of_week - assert_equal Time.local(2008,1,6,23,59,59,999999.999), Time.local(2007,12,31,10,10,10).end_of_week - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,8,27,0,0,0).end_of_week #monday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,8,28,0,0,0).end_of_week #tuesday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,8,29,0,0,0).end_of_week #wednesday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,8,30,0,0,0).end_of_week #thursday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,8,31,0,0,0).end_of_week #friday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,9,01,0,0,0).end_of_week #saturday - assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,9,02,0,0,0).end_of_week #sunday + assert_equal Time.local(2008,1,6,23,59,59,Rational(999999999, 1000)), Time.local(2007,12,31,10,10,10).end_of_week + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,27,0,0,0).end_of_week #monday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,28,0,0,0).end_of_week #tuesday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,29,0,0,0).end_of_week #wednesday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,30,0,0,0).end_of_week #thursday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,8,31,0,0,0).end_of_week #friday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,9,01,0,0,0).end_of_week #saturday + assert_equal Time.local(2007,9,2,23,59,59,Rational(999999999, 1000)), Time.local(2007,9,02,0,0,0).end_of_week #sunday end def test_end_of_hour - assert_equal Time.local(2005,2,4,19,59,59,999999.999), Time.local(2005,2,4,19,30,10).end_of_hour + assert_equal Time.local(2005,2,4,19,59,59,Rational(999999999, 1000)), Time.local(2005,2,4,19,30,10).end_of_hour end def test_end_of_month - assert_equal Time.local(2005,3,31,23,59,59,999999.999), Time.local(2005,3,20,10,10,10).end_of_month - assert_equal Time.local(2005,2,28,23,59,59,999999.999), Time.local(2005,2,20,10,10,10).end_of_month - assert_equal Time.local(2005,4,30,23,59,59,999999.999), Time.local(2005,4,20,10,10,10).end_of_month + assert_equal Time.local(2005,3,31,23,59,59,Rational(999999999, 1000)), Time.local(2005,3,20,10,10,10).end_of_month + assert_equal Time.local(2005,2,28,23,59,59,Rational(999999999, 1000)), Time.local(2005,2,20,10,10,10).end_of_month + assert_equal Time.local(2005,4,30,23,59,59,Rational(999999999, 1000)), Time.local(2005,4,20,10,10,10).end_of_month end def test_end_of_quarter - assert_equal Time.local(2007,3,31,23,59,59,999999.999), Time.local(2007,2,15,10,10,10).end_of_quarter - assert_equal Time.local(2007,3,31,23,59,59,999999.999), Time.local(2007,3,31,0,0,0).end_of_quarter - assert_equal Time.local(2007,12,31,23,59,59,999999.999), Time.local(2007,12,21,10,10,10).end_of_quarter - assert_equal Time.local(2007,6,30,23,59,59,999999.999), Time.local(2007,4,1,0,0,0).end_of_quarter - assert_equal Time.local(2008,6,30,23,59,59,999999.999), Time.local(2008,5,31,0,0,0).end_of_quarter + assert_equal Time.local(2007,3,31,23,59,59,Rational(999999999, 1000)), Time.local(2007,2,15,10,10,10).end_of_quarter + assert_equal Time.local(2007,3,31,23,59,59,Rational(999999999, 1000)), Time.local(2007,3,31,0,0,0).end_of_quarter + assert_equal Time.local(2007,12,31,23,59,59,Rational(999999999, 1000)), Time.local(2007,12,21,10,10,10).end_of_quarter + assert_equal Time.local(2007,6,30,23,59,59,Rational(999999999, 1000)), Time.local(2007,4,1,0,0,0).end_of_quarter + assert_equal Time.local(2008,6,30,23,59,59,Rational(999999999, 1000)), Time.local(2008,5,31,0,0,0).end_of_quarter end def test_end_of_year - assert_equal Time.local(2007,12,31,23,59,59,999999.999), Time.local(2007,2,22,10,10,10).end_of_year - assert_equal Time.local(2007,12,31,23,59,59,999999.999), Time.local(2007,12,31,10,10,10).end_of_year + assert_equal Time.local(2007,12,31,23,59,59,Rational(999999999, 1000)), Time.local(2007,2,22,10,10,10).end_of_year + assert_equal Time.local(2007,12,31,23,59,59,Rational(999999999, 1000)), Time.local(2007,12,31,10,10,10).end_of_year end def test_beginning_of_year @@ -517,7 +517,7 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2006,11,15), Time.local(2006,11,23,0,0,0).prev_week(:wednesday) end end - + def test_last_week with_env_tz 'US/Eastern' do assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).last_week @@ -828,24 +828,32 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_all_day - assert_equal Time.local(2011,6,7,0,0,0)..Time.local(2011,6,7,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_day + assert_equal Time.local(2011,6,7,0,0,0)..Time.local(2011,6,7,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_day + end + + def test_all_day_with_timezone + beginning_of_day = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], Time.local(2011,6,7,0,0,0)) + end_of_day = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], Time.local(2011,6,7,23,59,59,Rational(999999999, 1000))) + + assert_equal beginning_of_day, ActiveSupport::TimeWithZone.new(Time.local(2011,6,7,10,10,10), ActiveSupport::TimeZone["Hawaii"]).all_day.begin + assert_equal end_of_day, ActiveSupport::TimeWithZone.new(Time.local(2011,6,7,10,10,10), ActiveSupport::TimeZone["Hawaii"]).all_day.end end def test_all_week - assert_equal Time.local(2011,6,6,0,0,0)..Time.local(2011,6,12,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_week - assert_equal Time.local(2011,6,5,0,0,0)..Time.local(2011,6,11,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_week(:sunday) + assert_equal Time.local(2011,6,6,0,0,0)..Time.local(2011,6,12,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_week + assert_equal Time.local(2011,6,5,0,0,0)..Time.local(2011,6,11,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_week(:sunday) end def test_all_month - assert_equal Time.local(2011,6,1,0,0,0)..Time.local(2011,6,30,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_month + assert_equal Time.local(2011,6,1,0,0,0)..Time.local(2011,6,30,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_month end def test_all_quarter - assert_equal Time.local(2011,4,1,0,0,0)..Time.local(2011,6,30,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_quarter + assert_equal Time.local(2011,4,1,0,0,0)..Time.local(2011,6,30,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_quarter end def test_all_year - assert_equal Time.local(2011,1,1,0,0,0)..Time.local(2011,12,31,23,59,59,999999.999), Time.local(2011,6,7,10,10,10).all_year + assert_equal Time.local(2011,1,1,0,0,0)..Time.local(2011,12,31,23,59,59,Rational(999999999, 1000)), Time.local(2011,6,7,10,10,10).all_year end protected diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index b62337e31b..1293f104e5 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -80,6 +80,14 @@ class TimeWithZoneTest < ActiveSupport::TestCase ActiveSupport.use_standard_json_time_format = old end + def test_nsec + local = Time.local(2011,6,7,23,59,59,Rational(999999999, 1000)) + with_zone = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], local) + + assert_equal local.nsec, with_zone.nsec + assert_equal with_zone.nsec, 999999999 + end + def test_strftime assert_equal '1999-12-31 19:00:00 EST -0500', @twz.strftime('%Y-%m-%d %H:%M:%S %Z %z') end diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb index 1e5ce67a58..845c54f416 100644 --- a/railties/lib/rails/application/route_inspector.rb +++ b/railties/lib/rails/application/route_inspector.rb @@ -16,7 +16,7 @@ module Rails class_name = app.class.name.to_s if class_name == "ActionDispatch::Routing::Mapper::Constraints" rack_app(app.app) - elsif class_name !~ /^ActionDispatch::Routing/ + elsif class_name == "ActionDispatch::Routing::Redirect" || class_name !~ /^ActionDispatch::Routing/ app end end @@ -67,7 +67,7 @@ module Rails @engines = Hash.new end - def format all_routes, filter = nil + def format(all_routes, filter = nil) if filter all_routes = all_routes.select{ |route| route.defaults[:controller] == filter } end diff --git a/railties/test/application/route_inspect_test.rb b/railties/test/application/route_inspect_test.rb index 453ba8196c..31af1ca6dc 100644 --- a/railties/test/application/route_inspect_test.rb +++ b/railties/test/application/route_inspect_test.rb @@ -16,6 +16,11 @@ module ApplicationTests Rails.stubs(:env).returns("development") end + def draw(&block) + @set.draw(&block) + @inspector.format(@set.routes) + end + def test_displaying_routes_for_engines engine = Class.new(Rails::Engine) do def self.to_s @@ -26,12 +31,11 @@ module ApplicationTests get '/cart', :to => 'cart#show' end - @set.draw do + output = draw do get '/custom/assets', :to => 'custom_assets#show' mount engine => "/blog", :as => "blog" end - output = @inspector.format @set.routes expected = [ "custom_assets GET /custom/assets(.:format) custom_assets#show", " blog /blog Blog::Engine", @@ -42,26 +46,23 @@ module ApplicationTests end def test_cart_inspect - @set.draw do + output = draw do get '/cart', :to => 'cart#show' end - output = @inspector.format @set.routes assert_equal ["cart GET /cart(.:format) cart#show"], output end def test_inspect_shows_custom_assets - @set.draw do + output = draw do get '/custom/assets', :to => 'custom_assets#show' end - output = @inspector.format @set.routes assert_equal ["custom_assets GET /custom/assets(.:format) custom_assets#show"], output end def test_inspect_routes_shows_resources_route - @set.draw do + output = draw do resources :articles end - output = @inspector.format @set.routes expected = [ " articles GET /articles(.:format) articles#index", " POST /articles(.:format) articles#create", @@ -75,50 +76,44 @@ module ApplicationTests end def test_inspect_routes_shows_root_route - @set.draw do + output = draw do root :to => 'pages#main' end - output = @inspector.format @set.routes assert_equal ["root GET / pages#main"], output end def test_inspect_routes_shows_dynamic_action_route - @set.draw do + output = draw do get 'api/:action' => 'api' end - output = @inspector.format @set.routes assert_equal [" GET /api/:action(.:format) api#:action"], output end def test_inspect_routes_shows_controller_and_action_only_route - @set.draw do + output = draw do get ':controller/:action' end - output = @inspector.format @set.routes assert_equal [" GET /:controller/:action(.:format) :controller#:action"], output end def test_inspect_routes_shows_controller_and_action_route_with_constraints - @set.draw do + output = draw do get ':controller(/:action(/:id))', :id => /\d+/ end - output = @inspector.format @set.routes assert_equal [" GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"], output end def test_rake_routes_shows_route_with_defaults - @set.draw do + output = draw do get 'photos/:id' => 'photos#show', :defaults => {:format => 'jpg'} end - output = @inspector.format @set.routes assert_equal [%Q[ GET /photos/:id(.:format) photos#show {:format=>"jpg"}]], output end def test_rake_routes_shows_route_with_constraints - @set.draw do + output = draw do get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/ end - output = @inspector.format @set.routes assert_equal [" GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}"], output end @@ -128,10 +123,9 @@ module ApplicationTests end def test_rake_routes_shows_route_with_rack_app - @set.draw do + output = draw do get 'foo/:id' => RackApp, :id => /[A-Z]\d{5}/ end - output = @inspector.format @set.routes assert_equal [" GET /foo/:id(.:format) #{RackApp.name} {:id=>/[A-Z]\\d{5}/}"], output end @@ -142,23 +136,30 @@ module ApplicationTests end end - @set.draw do + output = draw do scope :constraint => constraint.new do mount RackApp => '/foo' end end - output = @inspector.format @set.routes assert_equal [" /foo #{RackApp.name} {:constraint=>( my custom constraint )}"], output end def test_rake_routes_dont_show_app_mounted_in_assets_prefix - @set.draw do + output = draw do get '/sprockets' => RackApp end - output = @inspector.format @set.routes assert_no_match(/RackApp/, output.first) assert_no_match(/\/sprockets/, output.first) end + + def test_redirect + output = draw do + match '/foo' => redirect("/bar") + match '/foo2' => redirect("/bar", status: 307) + end + assert_equal " foo /foo(.:format) Redirect (301)", output[0] + assert_equal "foo2 /foo2(.:format) Redirect (307)", output[1] + end end end |