diff options
Diffstat (limited to 'activerecord/test')
25 files changed, 378 insertions, 147 deletions
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index 4c90d06732..b0759dffde 100644 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -134,12 +134,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert_equal [["STRICT_ALL_TABLES"]], result.rows end - def test_mysql_strict_mode_disabled_dont_override_global_sql_mode + def test_mysql_strict_mode_disabled run_without_connection do |orig_connection| ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) - global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode" - session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" - assert_equal global_sql_mode.rows, session_sql_mode.rows + result = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" + assert_equal [['']], result.rows end end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 65f50e77bb..3b35e69e0d 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -60,12 +60,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert_equal [["STRICT_ALL_TABLES"]], result.rows end - def test_mysql_strict_mode_disabled_dont_override_global_sql_mode + def test_mysql_strict_mode_disabled run_without_connection do |orig_connection| ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) - global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode" - session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" - assert_equal global_sql_mode.rows, session_sql_mode.rows + result = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" + assert_equal [['']], result.rows end end diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb index ec73ec35aa..9c49599d34 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -6,12 +6,12 @@ module ActiveRecord class SchemaMigrationsTest < ActiveRecord::TestCase def test_renaming_index_on_foreign_key connection.add_index "engines", "car_id" - connection.execute "ALTER TABLE engines ADD CONSTRAINT fk_engines_cars FOREIGN KEY (car_id) REFERENCES cars(id)" + connection.add_foreign_key :engines, :cars, name: "fk_engines_cars" connection.rename_index("engines", "index_engines_on_car_id", "idx_renamed") assert_equal ["idx_renamed"], connection.indexes("engines").map(&:name) ensure - connection.execute "ALTER TABLE engines DROP FOREIGN KEY fk_engines_cars" + connection.remove_foreign_key :engines, name: "fk_engines_cars" end def test_initializes_schema_migrations_for_encoding_utf8mb4 diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index f5b199b46a..d7ff81a382 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -60,6 +60,43 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase assert_equal(nil, UUIDType.last.guid) end + def test_treat_invalid_uuid_as_nil + uuid = UUIDType.create! guid: 'foobar' + assert_equal(nil, uuid.guid) + end + + def test_invalid_uuid_dont_modify_before_type_cast + uuid = UUIDType.new guid: 'foobar' + assert_equal 'foobar', uuid.guid_before_type_cast + end + + def test_rfc_4122_regex + # Valid uuids + ['A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11', + '{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}', + 'a0eebc999c0b4ef8bb6d6bb9bd380a11', + 'a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11', + '{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}'].each do |valid_uuid| + uuid = UUIDType.new guid: valid_uuid + assert_not_nil uuid.guid + end + + # Invalid uuids + [['A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'], + Hash.new, + 0, + 0.0, + true, + 'Z0000C99-9C0B-4EF8-BB6D-6BB9BD380A11', + '{a0eebc99-9c0b-4ef8-fb6d-6bb9bd380a11}', + 'a0eebc999r0b4ef8ab6d6bb9bd380a11', + 'a0ee-bc99------4ef8-bb6d-6bb9-bd38-0a11', + '{a0eebc99-bb6d6bb9-bd380a11}'].each do |invalid_uuid| + uuid = UUIDType.new guid: invalid_uuid + assert_nil uuid.guid + end + end + def test_uuid_formats ["A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11", "{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}", @@ -87,10 +124,26 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase t.string 'name' t.uuid 'other_uuid', default: 'uuid_generate_v4()' end + + # Create custom PostgreSQL function to generate UUIDs + # to test dumping tables which columns have defaults with custom functions + connection.execute <<-SQL + CREATE OR REPLACE FUNCTION my_uuid_generator() RETURNS uuid + AS $$ SELECT * FROM uuid_generate_v4() $$ + LANGUAGE SQL VOLATILE; + SQL + + # Create such a table with custom function as default value generator + connection.create_table('pg_uuids_2', id: :uuid, default: 'my_uuid_generator()') do |t| + t.string 'name' + t.uuid 'other_uuid_2', default: 'my_uuid_generator()' + end end teardown do drop_table "pg_uuids" + drop_table 'pg_uuids_2' + connection.execute 'DROP FUNCTION IF EXISTS my_uuid_generator();' end if ActiveRecord::Base.connection.supports_extensions? @@ -122,6 +175,13 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::TestCase assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: "uuid_generate_v1\(\)"/, schema.string) assert_match(/t\.uuid "other_uuid", default: "uuid_generate_v4\(\)"/, schema.string) end + + def test_schema_dumper_for_uuid_primary_key_with_custom_default + schema = StringIO.new + ActiveRecord::SchemaDumper.dump(connection, schema) + assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: "my_uuid_generator\(\)"/, schema.string) + assert_match(/t\.uuid "other_uuid_2", default: "my_uuid_generator\(\)"/, schema.string) + end end end diff --git a/activerecord/test/cases/adapters/postgresql/xml_test.rb b/activerecord/test/cases/adapters/postgresql/xml_test.rb index 48c6eeb62c..4165dd5ac9 100644 --- a/activerecord/test/cases/adapters/postgresql/xml_test.rb +++ b/activerecord/test/cases/adapters/postgresql/xml_test.rb @@ -11,7 +11,7 @@ class PostgresqlXMLTest < ActiveRecord::TestCase begin @connection.transaction do @connection.create_table('xml_data_type') do |t| - t.xml 'payload', default: {} + t.xml 'payload' end end rescue ActiveRecord::StatementInvalid @@ -32,4 +32,17 @@ class PostgresqlXMLTest < ActiveRecord::TestCase @connection.execute %q|insert into xml_data_type (payload) VALUES(null)| assert_nil XmlDataType.first.payload end + + def test_round_trip + data = XmlDataType.new(payload: "<foo>bar</foo>") + assert_equal "<foo>bar</foo>", data.payload + data.save! + assert_equal "<foo>bar</foo>", data.reload.payload + end + + def test_update_all + data = XmlDataType.create! + XmlDataType.update_all(payload: "<bar>baz</bar>") + assert_equal "<bar>baz</bar>", data.reload.payload + end end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index 3bd53aa278..ac8332e2fa 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -103,6 +103,13 @@ module ActiveRecord }.new assert_raise(TypeError) { @conn.type_cast(quoted_id_obj, nil) } end + + def test_quoting_binary_strings + value = "hello".encode('ascii-8bit') + column = Column.new(nil, 1, SQLite3String.new) + + assert_equal "'hello'", @conn.quote(value, column) + end end end end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index c9bdfb88ae..25555bd75c 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -937,6 +937,8 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase end class BelongsToWithForeignKeyTest < ActiveRecord::TestCase + fixtures :authors, :author_addresses + def test_destroy_linked_models address = AuthorAddress.create! author = Author.create! name: "Author", author_address_id: address.id diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 3e5b7e655b..fe961e871c 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -837,6 +837,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end end + def test_calling_empty_with_counter_cache + post = posts(:welcome) + assert_queries(0) do + assert_not post.comments.empty? + end + end + def test_custom_named_counter_cache topic = topics(:first) diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 8ef351cda8..3720d6d251 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -153,6 +153,7 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase end def test_has_many_through_has_one_with_has_many_through_source_reflection_preload + ActiveRecord::Base.connection.table_alias_length # preheat cache members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) } groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy) diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 2048e0d5ad..ab67cf4085 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -143,7 +143,11 @@ class AttributeMethodsTest < ActiveRecord::TestCase # Syck calls respond_to? before actually calling initialize def test_respond_to_with_allocated_object - topic = Topic.allocate + klass = Class.new(ActiveRecord::Base) do + self.table_name = 'topics' + end + + topic = klass.allocate assert !topic.respond_to?("nothingness") assert !topic.respond_to?(:nothingness) assert_respond_to topic, "title" diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb index cdbb11fa32..dc20c3c676 100644 --- a/activerecord/test/cases/attribute_set_test.rb +++ b/activerecord/test/cases/attribute_set_test.rb @@ -88,15 +88,15 @@ module ActiveRecord assert_equal [:foo], attributes.keys end - test "uninitialized attributes return false for include?" do + test "uninitialized attributes return false for key?" do attributes = attributes_with_uninitialized_key - assert attributes.include?(:foo) - assert_not attributes.include?(:bar) + assert attributes.key?(:foo) + assert_not attributes.key?(:bar) end - test "unknown attributes return false for include?" do + test "unknown attributes return false for key?" do attributes = attributes_with_uninitialized_key - assert_not attributes.include?(:wibble) + assert_not attributes.key?(:wibble) end test "fetch_value returns the value for the given initialized attribute" do diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 8f83cf7cb4..4c0b0c868a 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1347,14 +1347,32 @@ class BasicsTest < ActiveRecord::TestCase end def test_compute_type_no_method_error - ActiveSupport::Dependencies.stubs(:constantize).raises(NoMethodError) + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(NoMethodError) assert_raises NoMethodError do ActiveRecord::Base.send :compute_type, 'InvalidModel' end end + def test_compute_type_on_undefined_method + error = nil + begin + Class.new(Author) do + alias_method :foo, :bar + end + rescue => e + error = e + end + + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(e) + + exception = assert_raises NameError do + ActiveRecord::Base.send :compute_type, 'InvalidModel' + end + assert_equal error.message, exception.message + end + def test_compute_type_argument_error - ActiveSupport::Dependencies.stubs(:constantize).raises(ArgumentError) + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(ArgumentError) assert_raises ArgumentError do ActiveRecord::Base.send :compute_type, 'InvalidModel' end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index ea73c561e9..69a7f25213 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -169,7 +169,19 @@ class DirtyTest < ActiveRecord::TestCase pirate = Pirate.create!(:catchphrase => 'Yar!') pirate.catchphrase = 'Ahoy!' - pirate.reset_catchphrase! + assert_deprecated do + pirate.reset_catchphrase! + end + assert_equal "Yar!", pirate.catchphrase + assert_equal Hash.new, pirate.changes + assert !pirate.catchphrase_changed? + end + + def test_restore_attribute! + pirate = Pirate.create!(:catchphrase => 'Yar!') + pirate.catchphrase = 'Ahoy!' + + pirate.restore_catchphrase! assert_equal "Yar!", pirate.catchphrase assert_equal Hash.new, pirate.changes assert !pirate.catchphrase_changed? @@ -398,7 +410,7 @@ class DirtyTest < ActiveRecord::TestCase def test_dup_objects_should_not_copy_dirty_flag_from_creator pirate = Pirate.create!(:catchphrase => "shiver me timbers") pirate_dup = pirate.dup - pirate_dup.reset_catchphrase! + pirate_dup.restore_catchphrase! pirate.catchphrase = "I love Rum" assert pirate.catchphrase_changed? assert !pirate_dup.catchphrase_changed? diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb index 93adbdd05b..763aa88f72 100644 --- a/activerecord/test/cases/migration/column_attributes_test.rb +++ b/activerecord/test/cases/migration/column_attributes_test.rb @@ -51,46 +51,46 @@ module ActiveRecord end end - # We specifically do a manual INSERT here, and then test only the SELECT - # functionality. This allows us to more easily catch INSERT being broken, - # but SELECT actually working fine. - def test_native_decimal_insert_manual_vs_automatic - correct_value = '0012345678901234567890.0123456789'.to_d - - connection.add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10' - - # Do a manual insertion - if current_adapter?(:OracleAdapter) - connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)" - elsif current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003 #before MySQL 5.0.3 decimals stored as strings - connection.execute "insert into test_models (wealth) values ('12345678901234567890.0123456789')" - elsif current_adapter?(:PostgreSQLAdapter) - connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)" - else - connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)" - end + unless current_adapter?(:SQLite3Adapter) + # We specifically do a manual INSERT here, and then test only the SELECT + # functionality. This allows us to more easily catch INSERT being broken, + # but SELECT actually working fine. + def test_native_decimal_insert_manual_vs_automatic + correct_value = '0012345678901234567890.0123456789'.to_d + + connection.add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10' + + # Do a manual insertion + if current_adapter?(:OracleAdapter) + connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)" + elsif current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003 #before MySQL 5.0.3 decimals stored as strings + connection.execute "insert into test_models (wealth) values ('12345678901234567890.0123456789')" + elsif current_adapter?(:PostgreSQLAdapter) + connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)" + else + connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)" + end - # SELECT - row = TestModel.first - assert_kind_of BigDecimal, row.wealth + # SELECT + row = TestModel.first + assert_kind_of BigDecimal, row.wealth - # If this assert fails, that means the SELECT is broken! - unless current_adapter?(:SQLite3Adapter) - assert_equal correct_value, row.wealth - end + # If this assert fails, that means the SELECT is broken! + unless current_adapter?(:SQLite3Adapter) + assert_equal correct_value, row.wealth + end - # Reset to old state - TestModel.delete_all + # Reset to old state + TestModel.delete_all - # Now use the Rails insertion - TestModel.create :wealth => BigDecimal.new("12345678901234567890.0123456789") + # Now use the Rails insertion + TestModel.create :wealth => BigDecimal.new("12345678901234567890.0123456789") - # SELECT - row = TestModel.first - assert_kind_of BigDecimal, row.wealth + # SELECT + row = TestModel.first + assert_kind_of BigDecimal, row.wealth - # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! - unless current_adapter?(:SQLite3Adapter) + # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! assert_equal correct_value, row.wealth end end @@ -121,54 +121,54 @@ module ActiveRecord end end - def test_native_types - add_column "test_models", "first_name", :string - add_column "test_models", "last_name", :string - add_column "test_models", "bio", :text - add_column "test_models", "age", :integer - add_column "test_models", "height", :float - add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10' - add_column "test_models", "birthday", :datetime - add_column "test_models", "favorite_day", :date - add_column "test_models", "moment_of_truth", :datetime - add_column "test_models", "male", :boolean - - TestModel.create :first_name => 'bob', :last_name => 'bobsen', - :bio => "I was born ....", :age => 18, :height => 1.78, - :wealth => BigDecimal.new("12345678901234567890.0123456789"), - :birthday => 18.years.ago, :favorite_day => 10.days.ago, - :moment_of_truth => "1782-10-10 21:40:18", :male => true - - bob = TestModel.first - assert_equal 'bob', bob.first_name - assert_equal 'bobsen', bob.last_name - assert_equal "I was born ....", bob.bio - assert_equal 18, bob.age - - # Test for 30 significant digits (beyond the 16 of float), 10 of them - # after the decimal place. - - unless current_adapter?(:SQLite3Adapter) + unless current_adapter?(:SQLite3Adapter) + def test_native_types + add_column "test_models", "first_name", :string + add_column "test_models", "last_name", :string + add_column "test_models", "bio", :text + add_column "test_models", "age", :integer + add_column "test_models", "height", :float + add_column "test_models", "wealth", :decimal, :precision => '30', :scale => '10' + add_column "test_models", "birthday", :datetime + add_column "test_models", "favorite_day", :date + add_column "test_models", "moment_of_truth", :datetime + add_column "test_models", "male", :boolean + + TestModel.create :first_name => 'bob', :last_name => 'bobsen', + :bio => "I was born ....", :age => 18, :height => 1.78, + :wealth => BigDecimal.new("12345678901234567890.0123456789"), + :birthday => 18.years.ago, :favorite_day => 10.days.ago, + :moment_of_truth => "1782-10-10 21:40:18", :male => true + + bob = TestModel.first + assert_equal 'bob', bob.first_name + assert_equal 'bobsen', bob.last_name + assert_equal "I was born ....", bob.bio + assert_equal 18, bob.age + + # Test for 30 significant digits (beyond the 16 of float), 10 of them + # after the decimal place. + assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth - end - assert_equal true, bob.male? + assert_equal true, bob.male? - assert_equal String, bob.first_name.class - assert_equal String, bob.last_name.class - assert_equal String, bob.bio.class - assert_equal Fixnum, bob.age.class - assert_equal Time, bob.birthday.class + assert_equal String, bob.first_name.class + assert_equal String, bob.last_name.class + assert_equal String, bob.bio.class + assert_equal Fixnum, bob.age.class + assert_equal Time, bob.birthday.class - if current_adapter?(:OracleAdapter) - # Oracle doesn't differentiate between date/time - assert_equal Time, bob.favorite_day.class - else - assert_equal Date, bob.favorite_day.class - end + if current_adapter?(:OracleAdapter) + # Oracle doesn't differentiate between date/time + assert_equal Time, bob.favorite_day.class + else + assert_equal Date, bob.favorite_day.class + end - assert_instance_of TrueClass, bob.male? - assert_kind_of BigDecimal, bob.wealth + assert_instance_of TrueClass, bob.male? + assert_kind_of BigDecimal, bob.wealth + end end if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter) diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb index 62b60f7f7b..bea9d6b2c9 100644 --- a/activerecord/test/cases/migration/create_join_table_test.rb +++ b/activerecord/test/cases/migration/create_join_table_test.rb @@ -119,6 +119,30 @@ module ActiveRecord assert !connection.tables.include?('artists_musics') end + + def test_create_and_drop_join_table_with_common_prefix + with_table_cleanup do + connection.create_join_table 'audio_artists', 'audio_musics' + assert_includes connection.tables, 'audio_artists_musics' + + connection.drop_join_table 'audio_artists', 'audio_musics' + assert !connection.tables.include?('audio_artists_musics'), "Should have dropped join table, but didn't" + end + end + + private + + def with_table_cleanup + tables_before = connection.tables + + yield + ensure + tables_after = connection.tables - tables_before + + tables_after.each do |table| + connection.execute "DROP TABLE #{table}" + end + end end end end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 6b840e16bb..84720585f2 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -895,4 +895,14 @@ class CopyMigrationsTest < ActiveRecord::TestCase ensure ActiveRecord::Base.logger = old end + + private + + def quietly + silence_stream(STDOUT) do + silence_stream(STDERR) do + yield + end + end + end end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index b41a7ee787..84abaf0291 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -87,7 +87,7 @@ class ReflectionTest < ActiveRecord::TestCase end def test_reflection_klass_for_nested_class_name - reflection = MacroReflection.new(:company, nil, nil, { :class_name => 'MyApplication::Business::Company' }, ActiveRecord::Base) + reflection = ActiveRecord::Reflection.create(:has_many, nil, nil, { :class_name => 'MyApplication::Business::Company' }, ActiveRecord::Base) assert_nothing_raised do assert_equal MyApplication::Business::Company, reflection.klass end @@ -97,21 +97,21 @@ class ReflectionTest < ActiveRecord::TestCase ActiveSupport::Inflector.inflections do |inflect| inflect.irregular 'plural_irregular', 'plurales_irregulares' end - reflection = AssociationReflection.new(:has_many, 'plurales_irregulares', nil, {}, ActiveRecord::Base) + reflection = ActiveRecord::Reflection.create(:has_many, 'plurales_irregulares', nil, {}, ActiveRecord::Base) assert_equal 'PluralIrregular', reflection.class_name end def test_aggregation_reflection reflection_for_address = AggregateReflection.new( - :composed_of, :address, nil, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer + :address, nil, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer ) reflection_for_balance = AggregateReflection.new( - :composed_of, :balance, nil, { :class_name => "Money", :mapping => %w(balance amount) }, Customer + :balance, nil, { :class_name => "Money", :mapping => %w(balance amount) }, Customer ) reflection_for_gps_location = AggregateReflection.new( - :composed_of, :gps_location, nil, { }, Customer + :gps_location, nil, { }, Customer ) assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location) @@ -135,7 +135,7 @@ class ReflectionTest < ActiveRecord::TestCase end def test_has_many_reflection - reflection_for_clients = AssociationReflection.new(:has_many, :clients, nil, { :order => "id", :dependent => :destroy }, Firm) + reflection_for_clients = ActiveRecord::Reflection.create(:has_many, :clients, nil, { :order => "id", :dependent => :destroy }, Firm) assert_equal reflection_for_clients, Firm.reflect_on_association(:clients) @@ -147,7 +147,7 @@ class ReflectionTest < ActiveRecord::TestCase end def test_has_one_reflection - reflection_for_account = AssociationReflection.new(:has_one, :account, nil, { :foreign_key => "firm_id", :dependent => :destroy }, Firm) + reflection_for_account = ActiveRecord::Reflection.create(:has_one, :account, nil, { :foreign_key => "firm_id", :dependent => :destroy }, Firm) assert_equal reflection_for_account, Firm.reflect_on_association(:account) assert_equal Account, Firm.reflect_on_association(:account).klass @@ -284,12 +284,12 @@ class ReflectionTest < ActiveRecord::TestCase end def test_association_primary_key_raises_when_missing_primary_key - reflection = ActiveRecord::Reflection::AssociationReflection.new(:fuu, :edge, nil, {}, Author) + reflection = ActiveRecord::Reflection.create(:has_many, :edge, nil, {}, Author) assert_raises(ActiveRecord::UnknownPrimaryKey) { reflection.association_primary_key } through = Class.new(ActiveRecord::Reflection::ThroughReflection) { define_method(:source_reflection) { reflection } - }.new(:fuu, :edge, nil, {}, Author) + }.new(reflection) assert_raises(ActiveRecord::UnknownPrimaryKey) { through.association_primary_key } end @@ -299,7 +299,7 @@ class ReflectionTest < ActiveRecord::TestCase end def test_active_record_primary_key_raises_when_missing_primary_key - reflection = ActiveRecord::Reflection::AssociationReflection.new(:fuu, :author, nil, {}, Edge) + reflection = ActiveRecord::Reflection.create(:has_many, :author, nil, {}, Edge) assert_raises(ActiveRecord::UnknownPrimaryKey) { reflection.active_record_primary_key } end @@ -317,32 +317,28 @@ class ReflectionTest < ActiveRecord::TestCase end def test_default_association_validation - assert AssociationReflection.new(:has_many, :clients, nil, {}, Firm).validate? + assert ActiveRecord::Reflection.create(:has_many, :clients, nil, {}, Firm).validate? - assert !AssociationReflection.new(:has_one, :client, nil, {}, Firm).validate? - assert !AssociationReflection.new(:belongs_to, :client, nil, {}, Firm).validate? - assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, nil, {}, Firm).validate? + assert !ActiveRecord::Reflection.create(:has_one, :client, nil, {}, Firm).validate? + assert !ActiveRecord::Reflection.create(:belongs_to, :client, nil, {}, Firm).validate? end def test_always_validate_association_if_explicit - assert AssociationReflection.new(:has_one, :client, nil, { :validate => true }, Firm).validate? - assert AssociationReflection.new(:belongs_to, :client, nil, { :validate => true }, Firm).validate? - assert AssociationReflection.new(:has_many, :clients, nil, { :validate => true }, Firm).validate? - assert AssociationReflection.new(:has_and_belongs_to_many, :clients, nil, { :validate => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:has_one, :client, nil, { :validate => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:belongs_to, :client, nil, { :validate => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:has_many, :clients, nil, { :validate => true }, Firm).validate? end def test_validate_association_if_autosave - assert AssociationReflection.new(:has_one, :client, nil, { :autosave => true }, Firm).validate? - assert AssociationReflection.new(:belongs_to, :client, nil, { :autosave => true }, Firm).validate? - assert AssociationReflection.new(:has_many, :clients, nil, { :autosave => true }, Firm).validate? - assert AssociationReflection.new(:has_and_belongs_to_many, :clients, nil, { :autosave => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:has_one, :client, nil, { :autosave => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:belongs_to, :client, nil, { :autosave => true }, Firm).validate? + assert ActiveRecord::Reflection.create(:has_many, :clients, nil, { :autosave => true }, Firm).validate? end def test_never_validate_association_if_explicit - assert !AssociationReflection.new(:has_one, :client, nil, { :autosave => true, :validate => false }, Firm).validate? - assert !AssociationReflection.new(:belongs_to, :client, nil, { :autosave => true, :validate => false }, Firm).validate? - assert !AssociationReflection.new(:has_many, :clients, nil, { :autosave => true, :validate => false }, Firm).validate? - assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, nil, { :autosave => true, :validate => false }, Firm).validate? + assert !ActiveRecord::Reflection.create(:has_one, :client, nil, { :autosave => true, :validate => false }, Firm).validate? + assert !ActiveRecord::Reflection.create(:belongs_to, :client, nil, { :autosave => true, :validate => false }, Firm).validate? + assert !ActiveRecord::Reflection.create(:has_many, :clients, nil, { :autosave => true, :validate => false }, Firm).validate? end def test_foreign_key @@ -364,11 +360,11 @@ class ReflectionTest < ActiveRecord::TestCase category = Struct.new(:table_name, :pluralize_table_names).new('categories', true) product = Struct.new(:table_name, :pluralize_table_names).new('products', true) - reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, nil, {}, product) + reflection = ActiveRecord::Reflection.create(:has_many, :categories, nil, {}, product) reflection.stubs(:klass).returns(category) assert_equal 'categories_products', reflection.join_table - reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, nil, {}, category) + reflection = ActiveRecord::Reflection.create(:has_many, :products, nil, {}, category) reflection.stubs(:klass).returns(product) assert_equal 'categories_products', reflection.join_table end @@ -377,11 +373,11 @@ class ReflectionTest < ActiveRecord::TestCase category = Struct.new(:table_name, :pluralize_table_names).new('catalog_categories', true) product = Struct.new(:table_name, :pluralize_table_names).new('catalog_products', true) - reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, nil, {}, product) + reflection = ActiveRecord::Reflection.create(:has_many, :categories, nil, {}, product) reflection.stubs(:klass).returns(category) assert_equal 'catalog_categories_products', reflection.join_table - reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, nil, {}, category) + reflection = ActiveRecord::Reflection.create(:has_many, :products, nil, {}, category) reflection.stubs(:klass).returns(product) assert_equal 'catalog_categories_products', reflection.join_table end @@ -390,11 +386,11 @@ class ReflectionTest < ActiveRecord::TestCase category = Struct.new(:table_name, :pluralize_table_names).new('catalog_categories', true) page = Struct.new(:table_name, :pluralize_table_names).new('content_pages', true) - reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, nil, {}, page) + reflection = ActiveRecord::Reflection.create(:has_many, :categories, nil, {}, page) reflection.stubs(:klass).returns(category) assert_equal 'catalog_categories_content_pages', reflection.join_table - reflection = AssociationReflection.new(:has_and_belongs_to_many, :pages, nil, {}, category) + reflection = ActiveRecord::Reflection.create(:has_many, :pages, nil, {}, category) reflection.stubs(:klass).returns(page) assert_equal 'catalog_categories_content_pages', reflection.join_table end @@ -403,11 +399,11 @@ class ReflectionTest < ActiveRecord::TestCase category = Struct.new(:table_name, :pluralize_table_names).new('categories', true) product = Struct.new(:table_name, :pluralize_table_names).new('products', true) - reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, nil, { :join_table => 'product_categories' }, product) + reflection = ActiveRecord::Reflection.create(:has_many, :categories, nil, { :join_table => 'product_categories' }, product) reflection.stubs(:klass).returns(category) assert_equal 'product_categories', reflection.join_table - reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, nil, { :join_table => 'product_categories' }, category) + reflection = ActiveRecord::Reflection.create(:has_many, :products, nil, { :join_table => 'product_categories' }, category) reflection.stubs(:klass).returns(product) assert_equal 'product_categories', reflection.join_table end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index 186a1a2ade..f8d87a3661 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -3,10 +3,11 @@ require 'models/topic' require 'models/reply' require 'models/person' require 'models/traffic_light' +require 'models/post' require 'bcrypt' class SerializedAttributeTest < ActiveRecord::TestCase - fixtures :topics + fixtures :topics, :posts MyObject = Struct.new :attribute1, :attribute2 @@ -67,6 +68,40 @@ class SerializedAttributeTest < ActiveRecord::TestCase assert_equal(orig.content, clone.content) end + def test_serialized_json_attribute_returns_unserialized_value + Topic.serialize :content, JSON + my_post = posts(:welcome) + + t = Topic.new(content: my_post) + t.save! + t.reload + + assert_instance_of(Hash, t.content) + assert_equal(my_post.id, t.content["id"]) + assert_equal(my_post.title, t.content["title"]) + end + + def test_json_read_legacy_null + Topic.serialize :content, JSON + + # Force a row to have a JSON "null" instead of a database NULL (this is how + # null values are saved on 4.1 and before) + id = Topic.connection.insert "INSERT INTO topics (content) VALUES('null')" + t = Topic.find(id) + + assert_nil t.content + end + + def test_json_read_db_null + Topic.serialize :content, JSON + + # Force a row to have a database NULL instead of a JSON "null" + id = Topic.connection.insert "INSERT INTO topics (content) VALUES(NULL)" + t = Topic.find(id) + + assert_nil t.content + end + def test_serialized_attribute_declared_in_subclass hash = { 'important1' => 'value1', 'important2' => 'value2' } important_topic = ImportantTopic.create("important" => hash) diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb index b6c5511849..23a170388e 100644 --- a/activerecord/test/cases/test_case.rb +++ b/activerecord/test/cases/test_case.rb @@ -13,6 +13,23 @@ module ActiveRecord assert_equal expected.to_s, actual.to_s, message end + def capture(stream) + stream = stream.to_s + captured_stream = Tempfile.new(stream) + stream_io = eval("$#{stream}") + origin_stream = stream_io.dup + stream_io.reopen(captured_stream) + + yield + + stream_io.rewind + return captured_stream.read + ensure + captured_stream.close + captured_stream.unlink + stream_io.reopen(origin_stream) + end + def capture_sql SQLCounter.clear_log yield diff --git a/activerecord/test/cases/type/decimal_test.rb b/activerecord/test/cases/type/decimal_test.rb new file mode 100644 index 0000000000..951cd879dd --- /dev/null +++ b/activerecord/test/cases/type/decimal_test.rb @@ -0,0 +1,33 @@ +require "cases/helper" + +module ActiveRecord + module Type + class DecimalTest < ActiveRecord::TestCase + def test_type_cast_decimal + type = Decimal.new + assert_equal BigDecimal.new("0"), type.type_cast_from_user(BigDecimal.new("0")) + assert_equal BigDecimal.new("123"), type.type_cast_from_user(123.0) + assert_equal BigDecimal.new("1"), type.type_cast_from_user(:"1") + end + + def test_type_cast_decimal_from_rational_with_precision + type = Decimal.new(precision: 2) + assert_equal BigDecimal("0.33"), type.type_cast_from_user(Rational(1, 3)) + end + + def test_type_cast_decimal_from_rational_without_precision_defaults_to_18_36 + type = Decimal.new + assert_equal BigDecimal("0.333333333333333333E0"), type.type_cast_from_user(Rational(1, 3)) + end + + def test_type_cast_decimal_from_object_responding_to_d + value = Object.new + def value.to_d + BigDecimal.new("1") + end + type = Decimal.new + assert_equal BigDecimal("1"), type.type_cast_from_user(value) + end + end + end +end diff --git a/activerecord/test/cases/types_test.rb b/activerecord/test/cases/types_test.rb index 47cf775cb6..5c54812f30 100644 --- a/activerecord/test/cases/types_test.rb +++ b/activerecord/test/cases/types_test.rb @@ -95,13 +95,6 @@ module ActiveRecord assert_not type.changed?(nil, nil, nil) end - def test_type_cast_decimal - type = Type::Decimal.new - assert_equal BigDecimal.new("0"), type.type_cast_from_user(BigDecimal.new("0")) - assert_equal BigDecimal.new("123"), type.type_cast_from_user(123.0) - assert_equal BigDecimal.new("1"), type.type_cast_from_user(:"1") - end - def test_type_cast_binary type = Type::Binary.new assert_equal nil, type.type_cast_from_user(nil) diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 9f1d110ddb..bce59b4fcd 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -1,5 +1,6 @@ require 'cases/helper' require 'models/topic' +require 'models/reply' require 'models/post' require 'models/author' diff --git a/activerecord/test/models/face.rb b/activerecord/test/models/face.rb index 3d7f0626e2..91e46f83e5 100644 --- a/activerecord/test/models/face.rb +++ b/activerecord/test/models/face.rb @@ -1,7 +1,8 @@ class Face < ActiveRecord::Base belongs_to :man, :inverse_of => :face belongs_to :polymorphic_man, :polymorphic => true, :inverse_of => :polymorphic_face - belongs_to :polymorphic_man_without_inverse, :polymorphic => true + # Oracle identifier lengh is limited to 30 bytes or less, `polymorphic` renamed `poly` + belongs_to :poly_man_without_inverse, :polymorphic => true # These is a "broken" inverse_of for the purposes of testing belongs_to :horrible_man, :class_name => 'Man', :inverse_of => :horrible_face belongs_to :horrible_polymorphic_man, :polymorphic => true, :inverse_of => :horrible_polymorphic_face diff --git a/activerecord/test/models/man.rb b/activerecord/test/models/man.rb index a26491ce61..4fbb6b226b 100644 --- a/activerecord/test/models/man.rb +++ b/activerecord/test/models/man.rb @@ -1,7 +1,7 @@ class Man < ActiveRecord::Base has_one :face, :inverse_of => :man has_one :polymorphic_face, :class_name => 'Face', :as => :polymorphic_man, :inverse_of => :polymorphic_man - has_one :polymorphic_face_without_inverse, :class_name => 'Face', :as => :polymorphic_man_without_inverse + has_one :polymorphic_face_without_inverse, :class_name => 'Face', :as => :poly_man_without_inverse has_many :interests, :inverse_of => :man has_many :polymorphic_interests, :class_name => 'Interest', :as => :polymorphic_man, :inverse_of => :polymorphic_man # These are "broken" inverse_of associations for the purposes of testing diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 932c9ba5d9..a8b21904ac 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -781,8 +781,8 @@ ActiveRecord::Schema.define do t.integer :man_id t.integer :polymorphic_man_id t.string :polymorphic_man_type - t.integer :polymorphic_man_without_inverse_id - t.string :polymorphic_man_without_inverse_type + t.integer :poly_man_without_inverse_id + t.string :poly_man_without_inverse_type t.integer :horrible_polymorphic_man_id t.string :horrible_polymorphic_man_type end @@ -860,9 +860,8 @@ ActiveRecord::Schema.define do create_table :fk_test_has_pk, force: true, primary_key: "pk_id" do |t| end - execute "ALTER TABLE fk_test_has_fk ADD CONSTRAINT fk_name FOREIGN KEY (#{quote_column_name 'fk_id'}) REFERENCES #{quote_table_name 'fk_test_has_pk'} (#{quote_column_name 'pk_id'})" - - execute "ALTER TABLE lessons_students ADD CONSTRAINT student_id_fk FOREIGN KEY (#{quote_column_name 'student_id'}) REFERENCES #{quote_table_name 'students'} (#{quote_column_name 'id'})" + add_foreign_key :fk_test_has_fk, :fk_test_has_pk, column: "fk_id", name: "fk_name", primary_key: "pk_id" + add_foreign_key :lessons_students, :students end create_table :overloaded_types, force: true do |t| |