diff options
Diffstat (limited to 'activerecord/test')
22 files changed, 455 insertions, 250 deletions
diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb index 01e7334aad..3daef399d8 100644 --- a/activerecord/test/cases/adapters/postgresql/json_test.rb +++ b/activerecord/test/cases/adapters/postgresql/json_test.rb @@ -21,7 +21,7 @@ class PostgresqlJSONTest < ActiveRecord::TestCase end end rescue ActiveRecord::StatementInvalid - return skip "do not test on PG without json" + skip "do not test on PG without json" end @column = JsonDataType.columns.find { |c| c.name == 'payload' } end diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index a56b8ac791..5c2d8e1c1d 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -26,7 +26,7 @@ if ActiveRecord::Base.connection.supports_ranges? end end rescue ActiveRecord::StatementInvalid - return skip "do not test on PG without range" + skip "do not test on PG without range" end insert_range(id: 101, diff --git a/activerecord/test/cases/adapters/postgresql/xml_test.rb b/activerecord/test/cases/adapters/postgresql/xml_test.rb index bf14b378d8..dd2a727afe 100644 --- a/activerecord/test/cases/adapters/postgresql/xml_test.rb +++ b/activerecord/test/cases/adapters/postgresql/xml_test.rb @@ -18,7 +18,7 @@ class PostgresqlXMLTest < ActiveRecord::TestCase end end rescue ActiveRecord::StatementInvalid - return skip "do not test on PG without xml" + skip "do not test on PG without xml" end @column = XmlDataType.columns.find { |c| c.name == 'payload' } end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 0598ff25f8..02834edf7b 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -34,24 +34,30 @@ module ActiveRecord end def test_connect_with_url - original_connection = ActiveRecord::Base.remove_connection - tf = Tempfile.open 'whatever' - url = "sqlite3://#{tf.path}" - ActiveRecord::Base.establish_connection(url) - assert ActiveRecord::Base.connection - ensure - tf.close - tf.unlink - ActiveRecord::Base.establish_connection(original_connection) + skip "can't establish new connection when using memory db" if in_memory_db? + begin + original_connection = ActiveRecord::Base.remove_connection + tf = Tempfile.open 'whatever' + url = "sqlite3://#{tf.path}" + ActiveRecord::Base.establish_connection(url) + assert ActiveRecord::Base.connection + ensure + tf.close + tf.unlink + ActiveRecord::Base.establish_connection(original_connection) + end end def test_connect_memory_with_url - original_connection = ActiveRecord::Base.remove_connection - url = "sqlite3:///:memory:" - ActiveRecord::Base.establish_connection(url) - assert ActiveRecord::Base.connection - ensure - ActiveRecord::Base.establish_connection(original_connection) + skip "can't establish new connection when using memory db" if in_memory_db? + begin + original_connection = ActiveRecord::Base.remove_connection + url = "sqlite3:///:memory:" + ActiveRecord::Base.establish_connection(url) + assert ActiveRecord::Base.connection + ensure + ActiveRecord::Base.establish_connection(original_connection) + end end def test_valid_column @@ -183,7 +189,7 @@ module ActiveRecord DualEncoding.connection.execute(<<-eosql) CREATE TABLE dual_encodings ( id integer PRIMARY KEY AUTOINCREMENT, - name string, + name varchar(255), data binary ) eosql diff --git a/activerecord/test/cases/associations/eager_singularization_test.rb b/activerecord/test/cases/associations/eager_singularization_test.rb index 634f6b63ba..669569a774 100644 --- a/activerecord/test/cases/associations/eager_singularization_test.rb +++ b/activerecord/test/cases/associations/eager_singularization_test.rb @@ -1,128 +1,133 @@ require "cases/helper" -class Virus < ActiveRecord::Base - belongs_to :octopus -end -class Octopus < ActiveRecord::Base - has_one :virus -end -class Pass < ActiveRecord::Base - belongs_to :bus -end -class Bus < ActiveRecord::Base - has_many :passes -end -class Mess < ActiveRecord::Base - has_and_belongs_to_many :crises -end -class Crisis < ActiveRecord::Base - has_and_belongs_to_many :messes - has_many :analyses, :dependent => :destroy - has_many :successes, :through => :analyses - has_many :dresses, :dependent => :destroy - has_many :compresses, :through => :dresses -end -class Analysis < ActiveRecord::Base - belongs_to :crisis - belongs_to :success -end -class Success < ActiveRecord::Base - has_many :analyses, :dependent => :destroy - has_many :crises, :through => :analyses -end -class Dress < ActiveRecord::Base - belongs_to :crisis - has_many :compresses -end -class Compress < ActiveRecord::Base - belongs_to :dress -end - class EagerSingularizationTest < ActiveRecord::TestCase + class Virus < ActiveRecord::Base + belongs_to :octopus + end + + class Octopus < ActiveRecord::Base + has_one :virus + end + + class Pass < ActiveRecord::Base + belongs_to :bus + end + + class Bus < ActiveRecord::Base + has_many :passes + end + + class Mess < ActiveRecord::Base + has_and_belongs_to_many :crises + end + + class Crisis < ActiveRecord::Base + has_and_belongs_to_many :messes + has_many :analyses, :dependent => :destroy + has_many :successes, :through => :analyses + has_many :dresses, :dependent => :destroy + has_many :compresses, :through => :dresses + end + + class Analysis < ActiveRecord::Base + belongs_to :crisis + belongs_to :success + end + + class Success < ActiveRecord::Base + has_many :analyses, :dependent => :destroy + has_many :crises, :through => :analyses + end + + class Dress < ActiveRecord::Base + belongs_to :crisis + has_many :compresses + end + + class Compress < ActiveRecord::Base + belongs_to :dress + end def setup - if ActiveRecord::Base.connection.supports_migrations? - ActiveRecord::Base.connection.create_table :viri do |t| - t.column :octopus_id, :integer - t.column :species, :string - end - ActiveRecord::Base.connection.create_table :octopi do |t| - t.column :species, :string - end - ActiveRecord::Base.connection.create_table :passes do |t| - t.column :bus_id, :integer - t.column :rides, :integer - end - ActiveRecord::Base.connection.create_table :buses do |t| - t.column :name, :string - end - ActiveRecord::Base.connection.create_table :crises_messes, :id => false do |t| - t.column :crisis_id, :integer - t.column :mess_id, :integer - end - ActiveRecord::Base.connection.create_table :messes do |t| - t.column :name, :string - end - ActiveRecord::Base.connection.create_table :crises do |t| - t.column :name, :string - end - ActiveRecord::Base.connection.create_table :successes do |t| - t.column :name, :string - end - ActiveRecord::Base.connection.create_table :analyses do |t| - t.column :crisis_id, :integer - t.column :success_id, :integer - end - ActiveRecord::Base.connection.create_table :dresses do |t| - t.column :crisis_id, :integer - end - ActiveRecord::Base.connection.create_table :compresses do |t| - t.column :dress_id, :integer - end - @have_tables = true - else - @have_tables = false + skip 'Does not support migrations' unless connection.supports_migrations? + + connection.create_table :viri do |t| + t.column :octopus_id, :integer + t.column :species, :string + end + connection.create_table :octopi do |t| + t.column :species, :string + end + connection.create_table :passes do |t| + t.column :bus_id, :integer + t.column :rides, :integer + end + connection.create_table :buses do |t| + t.column :name, :string + end + connection.create_table :crises_messes, :id => false do |t| + t.column :crisis_id, :integer + t.column :mess_id, :integer + end + connection.create_table :messes do |t| + t.column :name, :string + end + connection.create_table :crises do |t| + t.column :name, :string + end + connection.create_table :successes do |t| + t.column :name, :string + end + connection.create_table :analyses do |t| + t.column :crisis_id, :integer + t.column :success_id, :integer + end + connection.create_table :dresses do |t| + t.column :crisis_id, :integer + end + connection.create_table :compresses do |t| + t.column :dress_id, :integer end end def teardown - ActiveRecord::Base.connection.drop_table :viri - ActiveRecord::Base.connection.drop_table :octopi - ActiveRecord::Base.connection.drop_table :passes - ActiveRecord::Base.connection.drop_table :buses - ActiveRecord::Base.connection.drop_table :crises_messes - ActiveRecord::Base.connection.drop_table :messes - ActiveRecord::Base.connection.drop_table :crises - ActiveRecord::Base.connection.drop_table :successes - ActiveRecord::Base.connection.drop_table :analyses - ActiveRecord::Base.connection.drop_table :dresses - ActiveRecord::Base.connection.drop_table :compresses + connection.drop_table :viri + connection.drop_table :octopi + connection.drop_table :passes + connection.drop_table :buses + connection.drop_table :crises_messes + connection.drop_table :messes + connection.drop_table :crises + connection.drop_table :successes + connection.drop_table :analyses + connection.drop_table :dresses + connection.drop_table :compresses + end + + def connection + ActiveRecord::Base.connection end def test_eager_no_extra_singularization_belongs_to - return unless @have_tables assert_nothing_raised do Virus.all.merge!(:includes => :octopus).to_a end end def test_eager_no_extra_singularization_has_one - return unless @have_tables assert_nothing_raised do Octopus.all.merge!(:includes => :virus).to_a end end def test_eager_no_extra_singularization_has_many - return unless @have_tables assert_nothing_raised do Bus.all.merge!(:includes => :passes).to_a end end def test_eager_no_extra_singularization_has_and_belongs_to_many - return unless @have_tables assert_nothing_raised do Crisis.all.merge!(:includes => :messes).to_a Mess.all.merge!(:includes => :crises).to_a @@ -130,14 +135,12 @@ class EagerSingularizationTest < ActiveRecord::TestCase end def test_eager_no_extra_singularization_has_many_through_belongs_to - return unless @have_tables assert_nothing_raised do Crisis.all.merge!(:includes => :successes).to_a end end def test_eager_no_extra_singularization_has_many_through_has_many - return unless @have_tables assert_nothing_raised do Crisis.all.merge!(:includes => :compresses).to_a end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 517d2674a7..fe5de44409 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -574,6 +574,13 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase @ship = @pirate.create_ship(:name => 'Nights Dirty Lightning') end + def teardown + # We are running without transactional fixtures and need to cleanup. + Bird.delete_all + @ship.delete + @pirate.delete + end + # reload def test_a_marked_for_destruction_record_should_not_be_be_marked_after_reload @pirate.mark_for_destruction diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index cb8e564da1..983bcd9826 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -626,6 +626,7 @@ class BasicsTest < ActiveRecord::TestCase assert_equal ["EUC-JP"], Weird.columns.map {|c| c.name.encoding.name }.uniq ensure silence_warnings { Encoding.default_internal = old_default_internal } + Weird.reset_column_information end end @@ -1129,7 +1130,7 @@ class BasicsTest < ActiveRecord::TestCase k = Class.new(ak) k.table_name = "projects" orig_name = k.sequence_name - return skip "sequences not supported by db" unless orig_name + skip "sequences not supported by db" unless orig_name assert_equal k.reset_sequence_name, orig_name end @@ -1301,9 +1302,11 @@ class BasicsTest < ActiveRecord::TestCase end def test_compute_type_nonexistent_constant - assert_raises NameError do + e = assert_raises NameError do ActiveRecord::Base.send :compute_type, 'NonexistentModel' end + assert_equal 'uninitialized constant ActiveRecord::Base::NonexistentModel', e.message + assert_equal 'ActiveRecord::Base::NonexistentModel', e.name end def test_compute_type_no_method_error diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index 3e33b30144..318cc5a32c 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -2,6 +2,133 @@ require "cases/helper" module ActiveRecord module ConnectionAdapters + + class MergeAndResolveDefaultUrlConfigTest < ActiveRecord::TestCase + + def klass + ActiveRecord::ConnectionHandling::MergeAndResolveDefaultUrlConfig + end + + def setup + @previous_database_url = ENV.delete("DATABASE_URL") + end + + def teardown + ENV["DATABASE_URL"] = @previous_database_url + end + + def test_string_connection + config = { "production" => "postgres://localhost/foo" } + actual = klass.new(config).resolve + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_url_sub_key + config = { "production" => { "url" => "postgres://localhost/foo" } } + actual = klass.new(config).resolve + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_hash + config = { "production" => { "adapter" => "postgres", "database" => "foo" } } + actual = klass.new(config).resolve + assert_equal config, actual + end + + def test_blank + config = {} + actual = klass.new(config).resolve + assert_equal config, actual + end + + def test_blank_with_database_url + ENV['DATABASE_URL'] = "postgres://localhost/foo" + + config = {} + actual = klass.new(config).resolve + expected = { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" } + assert_equal expected, actual["production"] + assert_equal expected, actual["development"] + assert_equal expected, actual["test"] + assert_equal nil, actual[:production] + assert_equal nil, actual[:development] + assert_equal nil, actual[:test] + end + + def test_sting_with_database_url + ENV['DATABASE_URL'] = "NOT-POSTGRES://localhost/NOT_FOO" + + config = { "production" => "postgres://localhost/foo" } + actual = klass.new(config).resolve + + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_url_sub_key_with_database_url + ENV['DATABASE_URL'] = "NOT-POSTGRES://localhost/NOT_FOO" + + config = { "production" => { "url" => "postgres://localhost/foo" } } + actual = klass.new(config).resolve + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost" + } + } + assert_equal expected, actual + end + + def test_merge_no_conflicts_with_database_url + ENV['DATABASE_URL'] = "postgres://localhost/foo" + + config = {"production" => { "pool" => "5" } } + actual = klass.new(config).resolve + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => "5" + } + } + assert_equal expected, actual + end + + def test_merge_conflicts_with_database_url + ENV['DATABASE_URL'] = "postgres://localhost/foo" + + config = {"production" => { "adapter" => "NOT-POSTGRES", "database" => "NOT-FOO", "pool" => "5" } } + actual = klass.new(config).resolve + expected = { "production" => + { "adapter" => "postgresql", + "database" => "foo", + "host" => "localhost", + "pool" => "5" + } + } + assert_equal expected, actual + end + end + class ConnectionHandlerTest < ActiveRecord::TestCase def setup @klass = Class.new(Base) { def self.name; 'klass'; end } diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index c09e58fbf1..1f98801e93 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -74,9 +74,9 @@ class EnumTest < ActiveRecord::TestCase end test "constant to access the mapping" do - assert_equal 0, Book::STATUS[:proposed] - assert_equal 1, Book::STATUS["written"] - assert_equal 2, Book::STATUS[:published] + assert_equal 0, Book.statuses[:proposed] + assert_equal 1, Book.statuses["written"] + assert_equal 2, Book.statuses[:published] end test "building new objects with enum scopes" do @@ -88,4 +88,8 @@ class EnumTest < ActiveRecord::TestCase assert Book.written.create.written? assert Book.read.create.read? end + + test "_before_type_cast returns the enum label (required for form fields)" do + assert_equal "proposed", @book.status_before_type_cast + end end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 5125d5df2a..9b575557de 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -891,11 +891,4 @@ class FinderTest < ActiveRecord::TestCase ActiveRecord::Base.send(:replace_bind_variables, statement, vars) end end - - def with_env_tz(new_tz = 'US/Eastern') - old_tz, ENV['TZ'] = ENV['TZ'], new_tz - yield - ensure - old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') - end end diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb index 96e581ab4c..367d04a154 100644 --- a/activerecord/test/cases/hot_compatibility_test.rb +++ b/activerecord/test/cases/hot_compatibility_test.rb @@ -5,7 +5,7 @@ class HotCompatibilityTest < ActiveRecord::TestCase setup do @klass = Class.new(ActiveRecord::Base) do - connection.create_table :hot_compatibilities do |t| + connection.create_table :hot_compatibilities, force: true do |t| t.string :foo t.string :bar end diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index cb0d374ef7..d2b5a06b55 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -1,10 +1,11 @@ -require "cases/helper" +require 'cases/helper' require 'models/company' require 'models/person' require 'models/post' require 'models/project' require 'models/subscriber' require 'models/vegetables' +require 'models/shop' class InheritanceTest < ActiveRecord::TestCase fixtures :companies, :projects, :subscribers, :accounts, :vegetables @@ -128,6 +129,17 @@ class InheritanceTest < ActiveRecord::TestCase assert_kind_of Cabbage, cabbage end + def test_alt_becomes_bang_resets_inheritance_type_column + vegetable = Vegetable.create!(name: "Red Pepper") + assert_nil vegetable.custom_type + + cabbage = vegetable.becomes!(Cabbage) + assert_equal "Cabbage", cabbage.custom_type + + vegetable = cabbage.becomes!(Vegetable) + assert_nil cabbage.custom_type + end + def test_inheritance_find_all companies = Company.all.merge!(:order => 'id').to_a assert_kind_of Firm, companies[0], "37signals should be a firm" @@ -356,4 +368,10 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase ensure ActiveRecord::Base.store_full_sti_class = true end + + def test_sti_type_from_attributes_disabled_in_non_sti_class + phone = Shop::Product::Type.new(name: 'Phone') + product = Shop::Product.new(:type => phone) + assert product.save + end end diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 2e71b1a40d..dfb8a608cb 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -3,12 +3,11 @@ require 'cases/helper' require 'models/company' require 'models/developer' -require 'models/car' -require 'models/bulb' require 'models/owner' +require 'models/pet' class IntegrationTest < ActiveRecord::TestCase - fixtures :companies, :developers, :owners + fixtures :companies, :developers, :owners, :pets def test_to_param_should_return_string assert_kind_of String, Client.first.to_param @@ -91,13 +90,14 @@ class IntegrationTest < ActiveRecord::TestCase end def test_cache_key_changes_when_child_touched - car = Car.create - Bulb.create(car: car) + owner = owners(:blackbeard) + pet = pets(:parrot) + + owner.update_column :updated_at, Time.current + key = owner.cache_key - key = car.cache_key - car.bulb.touch - car.reload - assert_not_equal key, car.cache_key + assert pet.touch + assert_not_equal key, owner.reload.cache_key end def test_cache_key_format_for_existing_record_with_nil_updated_timestamps diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 0363bf1048..1bda472d23 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -328,6 +328,7 @@ class MigrationTest < ActiveRecord::TestCase end def test_proper_table_name_on_migrator + reminder_class = new_isolated_reminder_class assert_deprecated do assert_equal "table", ActiveRecord::Migrator.proper_table_name('table') end @@ -335,30 +336,30 @@ class MigrationTest < ActiveRecord::TestCase assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table) end assert_deprecated do - assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder) + assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(reminder_class) end - Reminder.reset_table_name + reminder_class.reset_table_name assert_deprecated do - assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder) + assert_equal reminder_class.table_name, ActiveRecord::Migrator.proper_table_name(reminder_class) end # Use the model's own prefix/suffix if a model is given ActiveRecord::Base.table_name_prefix = "ARprefix_" ActiveRecord::Base.table_name_suffix = "_ARsuffix" - Reminder.table_name_prefix = 'prefix_' - Reminder.table_name_suffix = '_suffix' - Reminder.reset_table_name + reminder_class.table_name_prefix = 'prefix_' + reminder_class.table_name_suffix = '_suffix' + reminder_class.reset_table_name assert_deprecated do - assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder) + assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(reminder_class) end - Reminder.table_name_prefix = '' - Reminder.table_name_suffix = '' - Reminder.reset_table_name + reminder_class.table_name_prefix = '' + reminder_class.table_name_suffix = '' + reminder_class.reset_table_name # Use AR::Base's prefix/suffix if string or symbol is given ActiveRecord::Base.table_name_prefix = "prefix_" ActiveRecord::Base.table_name_suffix = "_suffix" - Reminder.reset_table_name + reminder_class.reset_table_name assert_deprecated do assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table') end @@ -368,28 +369,29 @@ class MigrationTest < ActiveRecord::TestCase end def test_proper_table_name_on_migration + reminder_class = new_isolated_reminder_class migration = ActiveRecord::Migration.new assert_equal "table", migration.proper_table_name('table') assert_equal "table", migration.proper_table_name(:table) - assert_equal "reminders", migration.proper_table_name(Reminder) - Reminder.reset_table_name - assert_equal Reminder.table_name, migration.proper_table_name(Reminder) + assert_equal "reminders", migration.proper_table_name(reminder_class) + reminder_class.reset_table_name + assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class) # Use the model's own prefix/suffix if a model is given ActiveRecord::Base.table_name_prefix = "ARprefix_" ActiveRecord::Base.table_name_suffix = "_ARsuffix" - Reminder.table_name_prefix = 'prefix_' - Reminder.table_name_suffix = '_suffix' - Reminder.reset_table_name - assert_equal "prefix_reminders_suffix", migration.proper_table_name(Reminder) - Reminder.table_name_prefix = '' - Reminder.table_name_suffix = '' - Reminder.reset_table_name + reminder_class.table_name_prefix = 'prefix_' + reminder_class.table_name_suffix = '_suffix' + reminder_class.reset_table_name + assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class) + reminder_class.table_name_prefix = '' + reminder_class.table_name_suffix = '' + reminder_class.reset_table_name # Use AR::Base's prefix/suffix if string or symbol is given ActiveRecord::Base.table_name_prefix = "prefix_" ActiveRecord::Base.table_name_suffix = "_suffix" - Reminder.reset_table_name + reminder_class.reset_table_name assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options) assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options) end @@ -532,11 +534,13 @@ class MigrationTest < ActiveRecord::TestCase end protected - def with_env_tz(new_tz = 'US/Eastern') - old_tz, ENV['TZ'] = ENV['TZ'], new_tz - yield - ensure - old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') + # This is needed to isolate class_attribute assignments like `table_name_prefix` + # for each test case. + def new_isolated_reminder_class + Class.new(Reminder) { + def self.name; "Reminder"; end + def self.base_class; self; end + } end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 5566563116..da8ae672fe 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -8,7 +8,7 @@ require 'rack' class QueryCacheTest < ActiveRecord::TestCase fixtures :tasks, :topics, :categories, :posts, :categories_posts - def setup + teardown do Task.connection.clear_query_cache ActiveRecord::Base.connection.disable_query_cache! end @@ -214,7 +214,7 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase Post.find(1) # change the column definition - Post.connection.change_column :posts, :title, :string, :limit => 80 + Post.connection.change_column :posts, :title, :string, limit: 80 assert_nothing_raised { Post.find(1) } # restore the old definition @@ -241,7 +241,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase def test_update Task.connection.expects(:clear_query_cache).times(2) - Task.cache do task = Task.find(1) task.starting = Time.now.utc @@ -251,7 +250,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase def test_destroy Task.connection.expects(:clear_query_cache).times(2) - Task.cache do Task.find(1).destroy end @@ -259,7 +257,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase def test_insert ActiveRecord::Base.connection.expects(:clear_query_cache).times(2) - Task.cache do Task.create! end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 031da8e6d6..afd5a69cef 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1511,17 +1511,13 @@ class RelationTest < ActiveRecord::TestCase assert !Post.all.respond_to?(:by_lifo) end - test "merge collapses wheres from the LHS only" do - left = Post.where(title: "omg").where(comments_count: 1) - right = Post.where(title: "wtf").where(title: "bbq") - - expected = [left.where_values[1]] + right.where_values - merged = left.merge(right) + def test_unscope_removes_binds + left = Post.where(id: Arel::Nodes::BindParam.new('?')) + column = Post.columns_hash['id'] + left.bind_values += [[column, 20]] - assert_equal expected, merged.where_values - assert !merged.to_sql.include?("omg") - assert merged.to_sql.include?("wtf") - assert merged.to_sql.include?("bbq") + relation = left.unscope(where: :id) + assert_equal [], relation.bind_values end def test_merging_removes_rhs_bind_parameters diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 741827446d..c085663efb 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -190,6 +190,8 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition elsif current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition + elsif current_adapter?(:SQLite3Adapter) && ActiveRecord::Base.connection.supports_partial_index? + assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition else assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition end diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 5644a35385..7e7d95841b 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -1,9 +1,11 @@ require "cases/helper" +require 'models/owner' +require 'models/pet' require 'models/topic' class TransactionCallbacksTest < ActiveRecord::TestCase self.use_transactional_fixtures = false - fixtures :topics + fixtures :topics, :owners, :pets class ReplyWithCallbacks < ActiveRecord::Base self.table_name = :topics @@ -28,14 +30,14 @@ class TransactionCallbacksTest < ActiveRecord::TestCase has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id" - after_commit{|record| record.send(:do_after_commit, nil)} - after_commit(:on => :create){|record| record.send(:do_after_commit, :create)} - after_commit(:on => :update){|record| record.send(:do_after_commit, :update)} - after_commit(:on => :destroy){|record| record.send(:do_after_commit, :destroy)} - after_rollback{|record| record.send(:do_after_rollback, nil)} - after_rollback(:on => :create){|record| record.send(:do_after_rollback, :create)} - after_rollback(:on => :update){|record| record.send(:do_after_rollback, :update)} - after_rollback(:on => :destroy){|record| record.send(:do_after_rollback, :destroy)} + after_commit { |record| record.do_after_commit(nil) } + after_commit(on: :create) { |record| record.do_after_commit(:create) } + after_commit(on: :update) { |record| record.do_after_commit(:update) } + after_commit(on: :destroy) { |record| record.do_after_commit(:destroy) } + after_rollback { |record| record.do_after_rollback(nil) } + after_rollback(on: :create) { |record| record.do_after_rollback(:create) } + after_rollback(on: :update) { |record| record.do_after_rollback(:update) } + after_rollback(on: :destroy) { |record| record.do_after_rollback(:destroy) } def history @history ||= [] @@ -65,7 +67,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def setup - @first, @second = TopicWithCallbacks.find(1, 3).sort_by { |t| t.id } + @first = TopicWithCallbacks.find(1) end def test_call_after_commit_after_transaction_commits @@ -77,40 +79,25 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record - @first.after_commit_block(:create){|r| r.history << :commit_on_create} - @first.after_commit_block(:update){|r| r.history << :commit_on_update} - @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy} - @first.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @first.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} + add_transaction_execution_blocks @first @first.save! assert_equal [:commit_on_update], @first.history end def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record - @first.after_commit_block(:create){|r| r.history << :commit_on_create} - @first.after_commit_block(:update){|r| r.history << :commit_on_update} - @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy} - @first.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @first.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} + add_transaction_execution_blocks @first @first.destroy assert_equal [:commit_on_destroy], @first.history end def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record - @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today) - @new_record.after_commit_block(:create){|r| r.history << :commit_on_create} - @new_record.after_commit_block(:update){|r| r.history << :commit_on_update} - @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy} - @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} - - @new_record.save! - assert_equal [:commit_on_create], @new_record.history + new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today) + add_transaction_execution_blocks new_record + + new_record.save! + assert_equal [:commit_on_create], new_record.history end def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record_if_create_succeeds_creating_through_association @@ -120,6 +107,13 @@ class TransactionCallbacksTest < ActiveRecord::TestCase assert_equal [], reply.history end + def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record_on_touch + add_transaction_execution_blocks @first + + @first.touch + assert_equal [:commit_on_update], @first.history + end + def test_call_after_rollback_after_transaction_rollsback @first.after_commit_block{|r| r.history << :after_commit} @first.after_rollback_block{|r| r.history << :after_rollback} @@ -133,12 +127,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record - @first.after_commit_block(:create){|r| r.history << :commit_on_create} - @first.after_commit_block(:update){|r| r.history << :commit_on_update} - @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy} - @first.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @first.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} + add_transaction_execution_blocks @first Topic.transaction do @first.save! @@ -148,13 +137,19 @@ class TransactionCallbacksTest < ActiveRecord::TestCase assert_equal [:rollback_on_update], @first.history end + def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record_on_touch + add_transaction_execution_blocks @first + + Topic.transaction do + @first.touch + raise ActiveRecord::Rollback + end + + assert_equal [:rollback_on_update], @first.history + end + def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record - @first.after_commit_block(:create){|r| r.history << :commit_on_create} - @first.after_commit_block(:update){|r| r.history << :commit_on_update} - @first.after_commit_block(:destroy){|r| r.history << :commit_on_update} - @first.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @first.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} + add_transaction_execution_blocks @first Topic.transaction do @first.destroy @@ -165,20 +160,15 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record - @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today) - @new_record.after_commit_block(:create){|r| r.history << :commit_on_create} - @new_record.after_commit_block(:update){|r| r.history << :commit_on_update} - @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy} - @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create} - @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update} - @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy} + new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today) + add_transaction_execution_blocks new_record Topic.transaction do - @new_record.save! + new_record.save! raise ActiveRecord::Rollback end - assert_equal [:rollback_on_create], @new_record.history + assert_equal [:rollback_on_create], new_record.history end def test_call_after_rollback_when_commit_fails @@ -205,23 +195,24 @@ class TransactionCallbacksTest < ActiveRecord::TestCase @first.after_rollback_block{|r| r.rollbacks(1)} @first.after_commit_block{|r| r.commits(1)} - def @second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end - def @second.commits(i=0); @commits ||= 0; @commits += i if i; end - @second.after_rollback_block{|r| r.rollbacks(1)} - @second.after_commit_block{|r| r.commits(1)} + second = TopicWithCallbacks.find(3) + def second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end + def second.commits(i=0); @commits ||= 0; @commits += i if i; end + second.after_rollback_block{|r| r.rollbacks(1)} + second.after_commit_block{|r| r.commits(1)} Topic.transaction do @first.save! Topic.transaction(:requires_new => true) do - @second.save! + second.save! raise ActiveRecord::Rollback end end assert_equal 1, @first.commits assert_equal 0, @first.rollbacks - assert_equal 0, @second.commits - assert_equal 1, @second.rollbacks + assert_equal 0, second.commits + assert_equal 1, second.rollbacks end def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails @@ -252,33 +243,61 @@ class TransactionCallbacksTest < ActiveRecord::TestCase def @first.last_after_transaction_error; @last_transaction_error; end @first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";} @first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";} - @second.after_commit_block{|r| r.history << :after_commit} - @second.after_rollback_block{|r| r.history << :after_rollback} + + second = TopicWithCallbacks.find(3) + second.after_commit_block{|r| r.history << :after_commit} + second.after_rollback_block{|r| r.history << :after_rollback} Topic.transaction do @first.save! - @second.save! + second.save! end assert_equal :commit, @first.last_after_transaction_error - assert_equal [:after_commit], @second.history + assert_equal [:after_commit], second.history - @second.history.clear + second.history.clear Topic.transaction do @first.save! - @second.save! + second.save! raise ActiveRecord::Rollback end assert_equal :rollback, @first.last_after_transaction_error - assert_equal [:after_rollback], @second.history + assert_equal [:after_rollback], second.history end def test_after_rollback_callbacks_should_validate_on_condition - assert_raise(ArgumentError) { Topic.send(:after_rollback, :on => :save) } + assert_raise(ArgumentError) { Topic.after_rollback(on: :save) } end def test_after_commit_callbacks_should_validate_on_condition - assert_raise(ArgumentError) { Topic.send(:after_commit, :on => :save) } + assert_raise(ArgumentError) { Topic.after_commit(on: :save) } end + + def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_call_callbacks_on_the_parent_object + pet = Pet.first + owner = pet.owner + flag = false + + owner.on_after_commit do + flag = true + end + + pet.name = "Fluffy the Third" + pet.save + + assert flag + end + + private + + def add_transaction_execution_blocks(record) + record.after_commit_block(:create) { |r| r.history << :commit_on_create } + record.after_commit_block(:update) { |r| r.history << :commit_on_update } + record.after_commit_block(:destroy) { |r| r.history << :commit_on_destroy } + record.after_rollback_block(:create) { |r| r.history << :rollback_on_create } + record.after_rollback_block(:update) { |r| r.history << :rollback_on_update } + record.after_rollback_block(:destroy) { |r| r.history << :rollback_on_destroy } + end end class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb index c4a15a79e2..db0f93f63b 100644 --- a/activerecord/test/models/car.rb +++ b/activerecord/test/models/car.rb @@ -15,7 +15,6 @@ class Car < ActiveRecord::Base scope :incl_engines, -> { includes(:engines) } scope :order_using_new_style, -> { order('name asc') } - end class CoolCar < Car diff --git a/activerecord/test/models/owner.rb b/activerecord/test/models/owner.rb index 1c7ed4aa3e..cf24502d3a 100644 --- a/activerecord/test/models/owner.rb +++ b/activerecord/test/models/owner.rb @@ -2,4 +2,21 @@ class Owner < ActiveRecord::Base self.primary_key = :owner_id has_many :pets, -> { order 'pets.name desc' } has_many :toys, :through => :pets + + after_commit :execute_blocks + + def blocks + @blocks ||= [] + end + + def on_after_commit(&block) + blocks << block + end + + def execute_blocks + blocks.each do |block| + block.call(self) + end + @blocks = [] + end end diff --git a/activerecord/test/models/shop.rb b/activerecord/test/models/shop.rb index 81414227ea..607a0a5b41 100644 --- a/activerecord/test/models/shop.rb +++ b/activerecord/test/models/shop.rb @@ -5,6 +5,11 @@ module Shop class Product < ActiveRecord::Base has_many :variants, :dependent => :delete_all + belongs_to :type + + class Type < ActiveRecord::Base + has_many :products + end end class Variant < ActiveRecord::Base diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index ddfc1ac0d6..9a7d918a25 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -557,9 +557,14 @@ ActiveRecord::Schema.define do create_table :products, force: true do |t| t.references :collection + t.references :type t.string :name end + create_table :product_types, force: true do |t| + t.string :name + end + create_table :projects, force: true do |t| t.string :name t.string :type |