aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb14
-rw-r--r--activerecord/test/cases/adapters/mysql2/enum_test.rb18
-rw-r--r--activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb44
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb31
-rw-r--r--activerecord/test/cases/adapters/mysql2/sp_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/extension_migration_test.rb12
-rw-r--r--activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb22
-rw-r--r--activerecord/test/cases/adapters/postgresql/range_test.rb42
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/uuid_test.rb17
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb11
-rw-r--r--activerecord/test/cases/ar_schema_test.rb4
-rw-r--r--activerecord/test/cases/associations/callbacks_test.rb8
-rw-r--r--activerecord/test/cases/associations/eager_test.rb8
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb19
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb12
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb2
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb14
-rw-r--r--activerecord/test/cases/associations/join_model_test.rb2
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb9
-rw-r--r--activerecord/test/cases/autosave_association_test.rb47
-rw-r--r--activerecord/test/cases/base_test.rb9
-rw-r--r--activerecord/test/cases/batches_test.rb45
-rw-r--r--activerecord/test/cases/bind_parameter_test.rb2
-rw-r--r--activerecord/test/cases/calculations_test.rb8
-rw-r--r--activerecord/test/cases/collection_cache_key_test.rb19
-rw-r--r--activerecord/test/cases/column_definition_test.rb28
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb6
-rw-r--r--activerecord/test/cases/counter_cache_test.rb2
-rw-r--r--activerecord/test/cases/database_statements_test.rb15
-rw-r--r--activerecord/test/cases/defaults_test.rb29
-rw-r--r--activerecord/test/cases/enum_test.rb10
-rw-r--r--activerecord/test/cases/finder_test.rb59
-rw-r--r--activerecord/test/cases/fixtures_test.rb4
-rw-r--r--activerecord/test/cases/inheritance_test.rb80
-rw-r--r--activerecord/test/cases/invalid_connection_test.rb2
-rw-r--r--activerecord/test/cases/migration/column_attributes_test.rb2
-rw-r--r--activerecord/test/cases/migration/compatibility_test.rb76
-rw-r--r--activerecord/test/cases/migration/references_foreign_key_test.rb20
-rw-r--r--activerecord/test/cases/migration/references_index_test.rb8
-rw-r--r--activerecord/test/cases/migration/references_statements_test.rb10
-rw-r--r--activerecord/test/cases/migration/rename_table_test.rb2
-rw-r--r--activerecord/test/cases/migration/table_and_index_test.rb24
-rw-r--r--activerecord/test/cases/migration_test.rb126
-rw-r--r--activerecord/test/cases/modules_test.rb4
-rw-r--r--activerecord/test/cases/multiple_db_test.rb2
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb45
-rw-r--r--activerecord/test/cases/persistence_test.rb2
-rw-r--r--activerecord/test/cases/primary_keys_test.rb29
-rw-r--r--activerecord/test/cases/reflection_test.rb10
-rw-r--r--activerecord/test/cases/relation/merging_test.rb7
-rw-r--r--activerecord/test/cases/relation/mutation_test.rb4
-rw-r--r--activerecord/test/cases/relation/or_test.rb10
-rw-r--r--activerecord/test/cases/relation/record_fetch_warning_test.rb4
-rw-r--r--activerecord/test/cases/relation/where_test.rb14
-rw-r--r--activerecord/test/cases/relation_test.rb11
-rw-r--r--activerecord/test/cases/relations_test.rb79
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb24
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb26
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb19
-rw-r--r--activerecord/test/cases/scoping/relation_scoping_test.rb20
-rw-r--r--activerecord/test/cases/store_test.rb3
-rw-r--r--activerecord/test/cases/suppressor_test.rb13
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb29
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb147
-rw-r--r--activerecord/test/cases/timestamp_test.rb11
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb26
-rw-r--r--activerecord/test/cases/transactions_test.rb5
-rw-r--r--activerecord/test/cases/validations/absence_validation_test.rb18
-rw-r--r--activerecord/test/cases/validations/length_validation_test.rb22
-rw-r--r--activerecord/test/cases/validations/presence_validation_test.rb36
-rw-r--r--activerecord/test/cases/validations/uniqueness_validation_test.rb72
-rw-r--r--activerecord/test/cases/validations_test.rb2
-rw-r--r--activerecord/test/fixtures/author_addresses.yml6
-rw-r--r--activerecord/test/fixtures/authors.yml2
-rw-r--r--activerecord/test/fixtures/naked/yml/trees.yml3
-rw-r--r--activerecord/test/fixtures/price_estimates.yml11
-rw-r--r--activerecord/test/models/author.rb2
-rw-r--r--activerecord/test/models/book.rb1
-rw-r--r--activerecord/test/models/car.rb2
-rw-r--r--activerecord/test/models/chef.rb4
-rw-r--r--activerecord/test/models/comment.rb1
-rw-r--r--activerecord/test/models/hotel.rb4
-rw-r--r--activerecord/test/models/mocktail_designer.rb2
-rw-r--r--activerecord/test/models/notification.rb1
-rw-r--r--activerecord/test/models/post.rb7
-rw-r--r--activerecord/test/models/uuid_item.rb6
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb38
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb62
-rw-r--r--activerecord/test/schema/postgresql_specific_schema.rb42
-rw-r--r--activerecord/test/schema/schema.rb16
92 files changed, 1358 insertions, 491 deletions
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index 8fabcfb5c0..575138eb2a 100644
--- a/activerecord/test/cases/adapters/mysql2/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -68,9 +68,6 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase
assert_equal 'utf8_general_ci', ARUnit2Model.connection.show_variable('collation_connection')
end
- # TODO: Below is a straight up copy/paste from mysql/connection_test.rb
- # I'm not sure what the correct way is to share these tests between
- # adapters in minitest.
def test_mysql_default_in_strict_mode
result = @connection.exec_query "SELECT @@SESSION.sql_mode"
assert_equal [["STRICT_ALL_TABLES"]], result.rows
@@ -83,14 +80,21 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase
assert_equal [['']], result.rows
end
end
-
+
def test_passing_arbitary_flags_to_adapter
run_without_connection do |orig_connection|
ActiveRecord::Base.establish_connection(orig_connection.merge({flags: Mysql2::Client::COMPRESS}))
assert_equal (Mysql2::Client::COMPRESS | Mysql2::Client::FOUND_ROWS), ActiveRecord::Base.connection.raw_connection.query_options[:flags]
end
end
-
+
+ def test_passing_flags_by_array_to_adapter
+ run_without_connection do |orig_connection|
+ ActiveRecord::Base.establish_connection(orig_connection.merge({flags: ['COMPRESS'] }))
+ assert_equal ["COMPRESS", "FOUND_ROWS"], ActiveRecord::Base.connection.raw_connection.query_options[:flags]
+ end
+ end
+
def test_mysql_strict_mode_specified_default
run_without_connection do |orig_connection|
ActiveRecord::Base.establish_connection(orig_connection.merge({strict: :default}))
diff --git a/activerecord/test/cases/adapters/mysql2/enum_test.rb b/activerecord/test/cases/adapters/mysql2/enum_test.rb
index bd732b5eca..35dbc76d1b 100644
--- a/activerecord/test/cases/adapters/mysql2/enum_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/enum_test.rb
@@ -5,6 +5,22 @@ class Mysql2EnumTest < ActiveRecord::Mysql2TestCase
end
def test_enum_limit
- assert_equal 6, EnumTest.columns.first.limit
+ column = EnumTest.columns_hash['enum_column']
+ assert_equal 8, column.limit
+ end
+
+ def test_should_not_be_blob_or_text_column
+ column = EnumTest.columns_hash['enum_column']
+ assert_not column.blob_or_text_column?
+ end
+
+ def test_should_not_be_unsigned
+ column = EnumTest.columns_hash['enum_column']
+ assert_not column.unsigned?
+ end
+
+ def test_should_not_be_bigint
+ column = EnumTest.columns_hash['enum_column']
+ assert_not column.bigint?
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
new file mode 100644
index 0000000000..4efd728754
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
@@ -0,0 +1,44 @@
+require "cases/helper"
+
+class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase
+ def setup
+ @conn = ActiveRecord::Base.connection
+ end
+
+ def test_columns_for_distinct_zero_orders
+ assert_equal "posts.id",
+ @conn.columns_for_distinct("posts.id", [])
+ end
+
+ def test_columns_for_distinct_one_order
+ assert_equal "posts.id, posts.created_at AS alias_0",
+ @conn.columns_for_distinct("posts.id", ["posts.created_at desc"])
+ end
+
+ def test_columns_for_distinct_few_orders
+ assert_equal "posts.id, posts.created_at AS alias_0, posts.position AS alias_1",
+ @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "posts.position asc"])
+ end
+
+ def test_columns_for_distinct_with_case
+ assert_equal(
+ 'posts.id, CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END AS alias_0',
+ @conn.columns_for_distinct('posts.id',
+ ["CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END"])
+ )
+ end
+
+ def test_columns_for_distinct_blank_not_nil_orders
+ assert_equal "posts.id, posts.created_at AS alias_0",
+ @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "", " "])
+ end
+
+ def test_columns_for_distinct_with_arel_order
+ order = Object.new
+ def order.to_sql
+ "posts.created_at desc"
+ end
+ assert_equal "posts.id, posts.created_at AS alias_0",
+ @conn.columns_for_distinct("posts.id", [order])
+ 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 396f235e77..7c89fda582 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
@@ -12,9 +12,30 @@ class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase
end
def test_initializes_schema_migrations_for_encoding_utf8mb4
- smtn = ActiveRecord::Migrator.schema_migrations_table_name
- connection.drop_table smtn, if_exists: true
+ with_encoding_utf8mb4 do
+ table_name = ActiveRecord::SchemaMigration.table_name
+ connection.drop_table table_name, if_exists: true
+ connection.initialize_schema_migrations_table
+
+ assert connection.column_exists?(table_name, :version, :string, collation: 'utf8_general_ci')
+ end
+ end
+
+ def test_initializes_internal_metadata_for_encoding_utf8mb4
+ with_encoding_utf8mb4 do
+ table_name = ActiveRecord::InternalMetadata.table_name
+ connection.drop_table table_name, if_exists: true
+
+ connection.initialize_internal_metadata_table
+
+ assert connection.column_exists?(table_name, :key, :string, collation: 'utf8_general_ci')
+ end
+ end
+
+ private
+
+ def with_encoding_utf8mb4
database_name = connection.current_database
database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'")
@@ -23,15 +44,11 @@ class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase
execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET utf8mb4")
- connection.initialize_schema_migrations_table
-
- limit = ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MAX_INDEX_LENGTH_FOR_CHARSETS_OF_4BYTES_MAXLEN
- assert connection.column_exists?(smtn, :version, :string, limit: limit)
+ yield
ensure
execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET #{original_charset} COLLATE #{original_collation}")
end
- private
def connection
@connection ||= ActiveRecord::Base.connection
end
diff --git a/activerecord/test/cases/adapters/mysql2/sp_test.rb b/activerecord/test/cases/adapters/mysql2/sp_test.rb
index cdaa2cca44..4197ba45f1 100644
--- a/activerecord/test/cases/adapters/mysql2/sp_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/sp_test.rb
@@ -22,6 +22,12 @@ class Mysql2StoredProcedureTest < ActiveRecord::Mysql2TestCase
assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_rows'"
end
+ def test_multi_results_from_select_one
+ row = @connection.select_one('CALL topics(1);')
+ assert_equal 'David', row['author_name']
+ assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_one'"
+ end
+
def test_multi_results_from_find_by_sql
topics = Topic.find_by_sql 'CALL topics(3);'
assert_equal 3, topics.size
diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb
index b2a805333c..b56c226763 100644
--- a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb
@@ -24,9 +24,9 @@ class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase
return skip("no extension support")
end
- @old_schema_migration_tabel_name = ActiveRecord::SchemaMigration.table_name
- @old_tabel_name_prefix = ActiveRecord::Base.table_name_prefix
- @old_tabel_name_suffix = ActiveRecord::Base.table_name_suffix
+ @old_schema_migration_table_name = ActiveRecord::SchemaMigration.table_name
+ @old_table_name_prefix = ActiveRecord::Base.table_name_prefix
+ @old_table_name_suffix = ActiveRecord::Base.table_name_suffix
ActiveRecord::Base.table_name_prefix = "p_"
ActiveRecord::Base.table_name_suffix = "_s"
@@ -36,11 +36,11 @@ class PostgresqlExtensionMigrationTest < ActiveRecord::PostgreSQLTestCase
end
def teardown
- ActiveRecord::Base.table_name_prefix = @old_tabel_name_prefix
- ActiveRecord::Base.table_name_suffix = @old_tabel_name_suffix
+ ActiveRecord::Base.table_name_prefix = @old_table_name_prefix
+ ActiveRecord::Base.table_name_suffix = @old_table_name_suffix
ActiveRecord::SchemaMigration.delete_all rescue nil
ActiveRecord::Migration.verbose = true
- ActiveRecord::SchemaMigration.table_name = @old_schema_migration_tabel_name
+ ActiveRecord::SchemaMigration.table_name = @old_schema_migration_table_name
super
end
diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
index e361521155..31e87722d9 100644
--- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb
@@ -53,12 +53,6 @@ module ActiveRecord
end
end
- def test_composite_primary_key
- with_example_table 'id serial, number serial, PRIMARY KEY (id, number)' do
- assert_nil @connection.primary_key('ex')
- end
- end
-
def test_primary_key_raises_error_if_table_not_found
assert_raises(ActiveRecord::StatementInvalid) do
@connection.primary_key('unobtainium')
@@ -139,8 +133,8 @@ module ActiveRecord
def test_sql_for_insert_with_returning_disabled
connection = connection_without_insert_returning
- result = connection.sql_for_insert('sql', nil, nil, nil, 'binds')
- assert_equal ['sql', 'binds'], result
+ sql, binds = connection.sql_for_insert('sql', nil, nil, nil, 'binds')
+ assert_equal ['sql', 'binds'], [sql, binds]
end
def test_serial_sequence
@@ -322,11 +316,6 @@ module ActiveRecord
end
end
- def test_substitute_at
- bind = @connection.substitute_at(nil)
- assert_equal Arel.sql('$1'), bind.to_sql
- end
-
def test_partial_index
with_example_table do
@connection.add_index 'ex', %w{ id number }, :name => 'partial', :where => "number > 100"
diff --git a/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb b/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb
new file mode 100644
index 0000000000..f1519db48b
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb
@@ -0,0 +1,22 @@
+require "cases/helper"
+require "models/developer"
+
+class PreparedStatementsTest < ActiveRecord::PostgreSQLTestCase
+ fixtures :developers
+
+ def setup
+ @default_prepared_statements = Developer.connection_config[:prepared_statements]
+ Developer.connection_config[:prepared_statements] = false
+ end
+
+ def teardown
+ Developer.connection_config[:prepared_statements] = @default_prepared_statements
+ end
+
+ def nothing_raised_with_falsy_prepared_statements
+ assert_nothing_raised do
+ Developer.where(id: 1)
+ end
+ end
+
+end
diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb
index 02b1083430..0edfa4ed9d 100644
--- a/activerecord/test/cases/adapters/postgresql/range_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/range_test.rb
@@ -4,11 +4,13 @@ require 'support/connection_helper'
if ActiveRecord::Base.connection.respond_to?(:supports_ranges?) && ActiveRecord::Base.connection.supports_ranges?
class PostgresqlRange < ActiveRecord::Base
self.table_name = "postgresql_ranges"
+ self.time_zone_aware_types += [:tsrange, :tstzrange]
end
class PostgresqlRangeTest < ActiveRecord::PostgreSQLTestCase
self.use_transactional_tests = false
include ConnectionHelper
+ include InTimeZone
def setup
@connection = PostgresqlRange.connection
@@ -160,6 +162,26 @@ _SQL
assert_nil @empty_range.float_range
end
+ def test_timezone_awareness_tzrange
+ tz = "Pacific Time (US & Canada)"
+
+ in_time_zone tz do
+ PostgresqlRange.reset_column_information
+ time_string = Time.current.to_s
+ time = Time.zone.parse(time_string)
+
+ record = PostgresqlRange.new(tstz_range: time_string..time_string)
+ assert_equal time..time, record.tstz_range
+ assert_equal ActiveSupport::TimeZone[tz], record.tstz_range.begin.time_zone
+
+ record.save!
+ record.reload
+
+ assert_equal time..time, record.tstz_range
+ assert_equal ActiveSupport::TimeZone[tz], record.tstz_range.begin.time_zone
+ end
+ end
+
def test_create_tstzrange
tstzrange = Time.parse('2010-01-01 14:30:00 +0100')...Time.parse('2011-02-02 14:30:00 CDT')
round_trip(@new_range, :tstz_range, tstzrange)
@@ -188,6 +210,26 @@ _SQL
Time.send(tz, 2010, 1, 1, 14, 30, 0)...Time.send(tz, 2010, 1, 1, 14, 30, 0))
end
+ def test_timezone_awareness_tsrange
+ tz = "Pacific Time (US & Canada)"
+
+ in_time_zone tz do
+ PostgresqlRange.reset_column_information
+ time_string = Time.current.to_s
+ time = Time.zone.parse(time_string)
+
+ record = PostgresqlRange.new(ts_range: time_string..time_string)
+ assert_equal time..time, record.ts_range
+ assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone
+
+ record.save!
+ record.reload
+
+ assert_equal time..time, record.ts_range
+ assert_equal ActiveSupport::TimeZone[tz], record.ts_range.begin.time_zone
+ end
+ end
+
def test_create_numrange
assert_equal_round_trip(@new_range, :num_range,
BigDecimal.new('0.5')...BigDecimal.new('1'))
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index 4aeca4d709..f50fe88b9b 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -166,7 +166,7 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase
end
end
- def test_raise_wraped_exception_on_bad_prepare
+ def test_raise_wrapped_exception_on_bad_prepare
assert_raises(ActiveRecord::StatementInvalid) do
@connection.exec_query "select * from developers where id = ?", 'sql', [bind_param(1)]
end
diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
index 049ed1732e..7628075ad2 100644
--- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb
@@ -146,8 +146,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase
end
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.create_table('pg_uuids', id: :uuid, default: 'uuid_generate_v1()') do |t|
t.string 'name'
t.uuid 'other_uuid', default: 'uuid_generate_v4()'
@@ -172,7 +170,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase
drop_table "pg_uuids"
drop_table 'pg_uuids_2'
connection.execute 'DROP FUNCTION IF EXISTS my_uuid_generator();'
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
@@ -200,14 +197,14 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase
def test_schema_dumper_for_uuid_primary_key
schema = dump_table_schema "pg_uuids"
- assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: "uuid_generate_v1\(\)"/, schema)
- assert_match(/t\.uuid "other_uuid", default: "uuid_generate_v4\(\)"/, schema)
+ assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: -> { "uuid_generate_v1\(\)" }/, schema)
+ assert_match(/t\.uuid "other_uuid", default: -> { "uuid_generate_v4\(\)" }/, schema)
end
def test_schema_dumper_for_uuid_primary_key_with_custom_default
schema = dump_table_schema "pg_uuids_2"
- assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: "my_uuid_generator\(\)"/, schema)
- assert_match(/t\.uuid "other_uuid_2", default: "my_uuid_generator\(\)"/, schema)
+ assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: -> { "my_uuid_generator\(\)" }/, schema)
+ assert_match(/t\.uuid "other_uuid_2", default: -> { "my_uuid_generator\(\)" }/, schema)
end
end
end
@@ -217,8 +214,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase
include SchemaDumpingHelper
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.create_table('pg_uuids', id: false) do |t|
t.primary_key :id, :uuid, default: nil
t.string 'name'
@@ -227,7 +222,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase
teardown do
drop_table "pg_uuids"
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
@@ -260,8 +254,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase
end
setup do
- enable_extension!('uuid-ossp', connection)
-
connection.transaction do
connection.create_table('pg_uuid_posts', id: :uuid) do |t|
t.string 'title'
@@ -276,7 +268,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase
teardown do
drop_table "pg_uuid_comments"
drop_table "pg_uuid_posts"
- disable_extension!('uuid-ossp', connection)
end
if ActiveRecord::Base.connection.supports_extensions?
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index a2fd1177a6..02c3358ba6 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -130,11 +130,6 @@ module ActiveRecord
assert_equal 'UTF-8', @conn.encoding
end
- def test_bind_value_substitute
- bind_param = @conn.substitute_at('foo')
- assert_equal Arel.sql('?'), bind_param.to_sql
- end
-
def test_exec_no_binds
with_example_table 'id int, data string' do
result = @conn.exec_query('SELECT id, data FROM ex')
@@ -405,12 +400,6 @@ module ActiveRecord
end
end
- def test_composite_primary_key
- with_example_table 'id integer, number integer, foo integer, PRIMARY KEY (id, number)' do
- assert_nil @conn.primary_key('ex')
- end
- end
-
def test_supports_extensions
assert_not @conn.supports_extensions?, 'does not support extensions'
end
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index 9d5327bf35..9c99689c1e 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -21,10 +21,10 @@ if ActiveRecord::Base.connection.supports_migrations?
ActiveRecord::Migration.verbose = @original_verbose
end
- def test_has_no_primary_key
+ def test_has_primary_key
old_primary_key_prefix_type = ActiveRecord::Base.primary_key_prefix_type
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
- assert_nil ActiveRecord::SchemaMigration.primary_key
+ assert_equal "version", ActiveRecord::SchemaMigration.primary_key
ActiveRecord::SchemaMigration.create_table
assert_difference "ActiveRecord::SchemaMigration.count", 1 do
diff --git a/activerecord/test/cases/associations/callbacks_test.rb b/activerecord/test/cases/associations/callbacks_test.rb
index a531e0e02c..a4298a25a6 100644
--- a/activerecord/test/cases/associations/callbacks_test.rb
+++ b/activerecord/test/cases/associations/callbacks_test.rb
@@ -177,14 +177,14 @@ class AssociationCallbacksTest < ActiveRecord::TestCase
end
def test_dont_add_if_before_callback_raises_exception
- assert !@david.unchangable_posts.include?(@authorless)
+ assert !@david.unchangeable_posts.include?(@authorless)
begin
- @david.unchangable_posts << @authorless
+ @david.unchangeable_posts << @authorless
rescue Exception
end
assert @david.post_log.empty?
- assert !@david.unchangable_posts.include?(@authorless)
+ assert !@david.unchangeable_posts.include?(@authorless)
@david.reload
- assert !@david.unchangable_posts.include?(@authorless)
+ assert !@david.unchangeable_posts.include?(@authorless)
end
end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 0c09713971..ac478cbb01 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -1216,7 +1216,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_join_eager_with_empty_order_should_generate_valid_sql
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
+ assert_nothing_raised do
Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
end
end
@@ -1402,4 +1402,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
post = Post.eager_load(:tags).where('tags.name = ?', 'General').first
assert_equal posts(:welcome), post
end
+
+ # CollectionProxy#reader is expensive, so the preloader avoids calling it.
+ test "preloading has_many_through association avoids calling association.reader" do
+ ActiveRecord::Associations::HasManyAssociation.any_instance.expects(:reader).never
+ Author.preload(:readonly_comments).first!
+ 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 ccb062f991..1bbca84bb2 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
@@ -146,6 +146,19 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_equal 1, country.treaties.count
end
+ def test_join_table_composite_primary_key_should_not_warn
+ country = Country.new(:name => 'India')
+ country.country_id = 'c1'
+ country.save!
+
+ treaty = Treaty.new(:name => 'peace')
+ treaty.treaty_id = 't1'
+ warning = capture(:stderr) do
+ country.treaties << treaty
+ end
+ assert_no_match(/WARNING: Rails does not support composite primary key\./, warning)
+ end
+
def test_has_and_belongs_to_many
david = Developer.find(1)
@@ -827,12 +840,12 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_no_queries { david.projects.columns }
end
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
+ def test_attributes_are_being_set_when_initialized_from_habtm_association_with_where_clause
new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
assert_equal new_developer.name, "Marcelo"
end
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_multiple_where_clauses
+ def test_attributes_are_being_set_when_initialized_from_habtm_association_with_multiple_where_clauses
new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
assert_equal new_developer.name, "Marcelo"
assert_equal new_developer.salary, 90_000
@@ -925,7 +938,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
end
def test_with_symbol_class_name
- assert_nothing_raised NoMethodError do
+ assert_nothing_raised do
DeveloperWithSymbolClassName.new
end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index ad157582a4..e975f4fbdd 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -408,6 +408,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
assert_no_queries do
+ bulbs.third_to_last()
+ bulbs.third_to_last({})
+ end
+
+ assert_no_queries do
+ bulbs.second_to_last()
+ bulbs.second_to_last({})
+ end
+
+ assert_no_queries do
bulbs.last()
bulbs.last({})
end
@@ -2271,7 +2281,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [], authors(:david).posts_with_signature.map(&:title)
end
- test 'associations autosaves when object is already persited' do
+ test 'associations autosaves when object is already persisted' do
bulb = Bulb.create!
tyre = Tyre.create!
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 226ecf5447..bb8c9fa19c 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -884,7 +884,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set
company = companies(:rails_core)
ids = [Developer.first.id, -9999]
- assert_raises(ActiveRecord::RecordNotFound) {company.developer_ids= ids}
+ assert_raises(ActiveRecord::AssociationTypeMismatch) {company.developer_ids= ids}
end
def test_build_a_model_from_hm_through_association_with_where_clause
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index 57d1c8feda..c9743e80d3 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -130,15 +130,15 @@ end
class InverseAssociationTests < ActiveRecord::TestCase
def test_should_allow_for_inverse_of_options_in_associations
- assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_many') do
+ assert_nothing_raised do
Class.new(ActiveRecord::Base).has_many(:wheels, :inverse_of => :car)
end
- assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_one') do
+ assert_nothing_raised do
Class.new(ActiveRecord::Base).has_one(:engine, :inverse_of => :car)
end
- assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on belongs_to') do
+ assert_nothing_raised do
Class.new(ActiveRecord::Base).belongs_to(:car, :inverse_of => :driver)
end
end
@@ -666,7 +666,7 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase
def test_trying_to_access_inverses_that_dont_exist_shouldnt_raise_an_error
# Ideally this would, if only for symmetry's sake with other association types
- assert_nothing_raised(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.horrible_polymorphic_man }
+ assert_nothing_raised { Face.first.horrible_polymorphic_man }
end
def test_trying_to_set_polymorphic_inverses_that_dont_exist_at_all_should_raise_an_error
@@ -676,7 +676,7 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase
def test_trying_to_set_polymorphic_inverses_that_dont_exist_on_the_instance_being_set_should_raise_an_error
# passes because Man does have the correct inverse_of
- assert_nothing_raised(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.polymorphic_man = Man.first }
+ assert_nothing_raised { Face.first.polymorphic_man = Man.first }
# fails because Interest does have the correct inverse_of
assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.first.polymorphic_man = Interest.first }
end
@@ -688,7 +688,7 @@ class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase
fixtures :men, :interests, :zines
def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models
- assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ assert_nothing_raised do
i = Interest.first
i.zine
i.man
@@ -696,7 +696,7 @@ class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase
end
def test_that_we_can_create_associations_that_have_the_same_reciprocal_name_from_different_models
- assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ assert_nothing_raised do
i = Interest.first
i.build_zine(:title => 'Get Some in Winter! 2008')
i.build_man(:name => 'Gordon')
diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb
index f6dddaf5b4..c850875619 100644
--- a/activerecord/test/cases/associations/join_model_test.rb
+++ b/activerecord/test/cases/associations/join_model_test.rb
@@ -88,7 +88,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
- assert_nothing_raised(NoMethodError) { tag.author_id }
+ assert_nothing_raised { tag.author_id }
end
def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 94dfbc3346..1db52af59b 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -714,6 +714,13 @@ class AttributeMethodsTest < ActiveRecord::TestCase
end
end
+ def test_time_zone_aware_attributes_dont_recurse_infinitely_on_invalid_values
+ in_time_zone "Pacific Time (US & Canada)" do
+ record = @target.new(bonus_time: [])
+ assert_equal nil, record.bonus_time
+ end
+ end
+
def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
Topic.skip_time_zone_conversion_for_attributes = [:field_a]
Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
@@ -791,7 +798,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_nil computer.system
end
- def test_global_methods_are_overwritte_when_subclassing
+ def test_global_methods_are_overwritten_when_subclassing
klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
subklass = Class.new(klass) do
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 0df8f1f798..3608063b01 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -433,6 +433,53 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config
end
+ def test_errors_details_should_be_set
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+ invalid_electron = Electron.new
+
+ molecule.electrons = [valid_electron, invalid_electron]
+
+ assert_not invalid_electron.valid?
+ assert valid_electron.valid?
+ assert_not molecule.valid?
+ assert_equal [{error: :blank}], molecule.errors.details["electrons.name"]
+ end
+
+ def test_errors_details_should_be_indexed_when_passed_as_array
+ guitar = Guitar.new
+ tuning_peg_valid = TuningPeg.new
+ tuning_peg_valid.pitch = 440.0
+ tuning_peg_invalid = TuningPeg.new
+
+ guitar.tuning_pegs = [tuning_peg_valid, tuning_peg_invalid]
+
+ assert_not tuning_peg_invalid.valid?
+ assert tuning_peg_valid.valid?
+ assert_not guitar.valid?
+ assert_equal [{error: :not_a_number, value: nil}] , guitar.errors.details["tuning_pegs[1].pitch"]
+ assert_equal [], guitar.errors.details["tuning_pegs.pitch"]
+ end
+
+ def test_errors_details_should_be_indexed_when_global_flag_is_set
+ old_attribute_config = ActiveRecord::Base.index_nested_attribute_errors
+ ActiveRecord::Base.index_nested_attribute_errors = true
+
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+ invalid_electron = Electron.new
+
+ molecule.electrons = [valid_electron, invalid_electron]
+
+ assert_not invalid_electron.valid?
+ assert valid_electron.valid?
+ assert_not molecule.valid?
+ assert_equal [{error: :blank}], molecule.errors.details["electrons[1].name"]
+ assert_equal [], molecule.errors.details["electrons.name"]
+ ensure
+ ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config
+ end
+
def test_valid_adding_with_nested_attributes
molecule = Molecule.new
valid_electron = Electron.new(name: 'electron')
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 79791af187..eef2d29d02 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -82,7 +82,6 @@ class BasicsTest < ActiveRecord::TestCase
classname = conn.class.name[/[^:]*$/]
badchar = {
'SQLite3Adapter' => '"',
- 'MysqlAdapter' => '`',
'Mysql2Adapter' => '`',
'PostgreSQLAdapter' => '"',
'OracleAdapter' => '"',
@@ -805,7 +804,7 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal dev.salary.amount, dup.salary.amount
assert !dup.persisted?
- # test if the attributes have been dupd
+ # test if the attributes have been duped
original_amount = dup.salary.amount
dev.salary.amount = 1
assert_equal original_amount, dup.salary.amount
@@ -1253,6 +1252,7 @@ class BasicsTest < ActiveRecord::TestCase
original_logger = ActiveRecord::Base.logger
log = StringIO.new
ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
+ ActiveRecord::Base.logger.level = Logger::DEBUG
ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => false) { ActiveRecord::Base.logger.debug "Quiet" }
assert_match(/Quiet/, log.string)
ensure
@@ -1275,9 +1275,10 @@ class BasicsTest < ActiveRecord::TestCase
UnloadablePost.send(:current_scope=, UnloadablePost.all)
UnloadablePost.unloadable
- assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
+ klass = UnloadablePost
+ assert_not_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
ActiveSupport::Dependencies.remove_unloadable_constants!
- assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, "UnloadablePost")
+ assert_nil ActiveRecord::Scoping::ScopeRegistry.value_for(:current_scope, klass)
ensure
Object.class_eval{ remove_const :UnloadablePost } if defined?(UnloadablePost)
end
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index da65336305..84aac3e721 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -38,7 +38,7 @@ class EachTest < ActiveRecord::TestCase
if Enumerator.method_defined? :size
def test_each_should_return_a_sized_enumerator
assert_equal 11, Post.find_each(batch_size: 1).size
- assert_equal 5, Post.find_each(batch_size: 2, begin_at: 7).size
+ assert_equal 5, Post.find_each(batch_size: 2, start: 7).size
assert_equal 11, Post.find_each(batch_size: 10_000).size
end
end
@@ -101,16 +101,16 @@ class EachTest < ActiveRecord::TestCase
def test_find_in_batches_should_start_from_the_start_option
assert_queries(@total) do
- Post.find_in_batches(batch_size: 1, begin_at: 2) do |batch|
+ Post.find_in_batches(batch_size: 1, start: 2) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
end
end
end
- def test_find_in_batches_should_end_at_the_end_option
+ def test_find_in_batches_should_end_at_the_finish_option
assert_queries(6) do
- Post.find_in_batches(batch_size: 1, end_at: 5) do |batch|
+ Post.find_in_batches(batch_size: 1, finish: 5) do |batch|
assert_kind_of Array, batch
assert_kind_of Post, batch.first
end
@@ -175,7 +175,7 @@ class EachTest < ActiveRecord::TestCase
def test_find_in_batches_should_not_modify_passed_options
assert_nothing_raised do
- Post.find_in_batches({ batch_size: 42, begin_at: 1 }.freeze){}
+ Post.find_in_batches({ batch_size: 42, start: 1 }.freeze){}
end
end
@@ -184,7 +184,7 @@ class EachTest < ActiveRecord::TestCase
start_nick = nick_order_subscribers.second.nick
subscribers = []
- Subscriber.find_in_batches(batch_size: 1, begin_at: start_nick) do |batch|
+ Subscriber.find_in_batches(batch_size: 1, start: start_nick) do |batch|
subscribers.concat(batch)
end
@@ -311,15 +311,15 @@ class EachTest < ActiveRecord::TestCase
def test_in_batches_should_start_from_the_start_option
post = Post.order('id ASC').where('id >= ?', 2).first
assert_queries(2) do
- relation = Post.in_batches(of: 1, begin_at: 2).first
+ relation = Post.in_batches(of: 1, start: 2).first
assert_equal post, relation.first
end
end
- def test_in_batches_should_end_at_the_end_option
+ def test_in_batches_should_end_at_the_finish_option
post = Post.order('id DESC').where('id <= ?', 5).first
assert_queries(7) do
- relation = Post.in_batches(of: 1, end_at: 5, load: true).reverse_each.first
+ relation = Post.in_batches(of: 1, finish: 5, load: true).reverse_each.first
assert_equal post, relation.last
end
end
@@ -371,7 +371,7 @@ class EachTest < ActiveRecord::TestCase
def test_in_batches_should_not_modify_passed_options
assert_nothing_raised do
- Post.in_batches({ of: 42, begin_at: 1 }.freeze){}
+ Post.in_batches({ of: 42, start: 1 }.freeze){}
end
end
@@ -380,7 +380,7 @@ class EachTest < ActiveRecord::TestCase
start_nick = nick_order_subscribers.second.nick
subscribers = []
- Subscriber.in_batches(of: 1, begin_at: start_nick) do |relation|
+ Subscriber.in_batches(of: 1, start: start_nick) do |relation|
subscribers.concat(relation)
end
@@ -441,32 +441,11 @@ class EachTest < ActiveRecord::TestCase
assert_equal 2, person.reload.author_id # incremented only once
end
- def test_find_in_batches_start_deprecated
- assert_deprecated do
- assert_queries(@total) do
- Post.find_in_batches(batch_size: 1, start: 2) do |batch|
- assert_kind_of Array, batch
- assert_kind_of Post, batch.first
- end
- end
- end
- end
-
- def test_find_each_start_deprecated
- assert_deprecated do
- assert_queries(@total) do
- Post.find_each(batch_size: 1, start: 2) do |post|
- assert_kind_of Post, post
- end
- end
- end
- end
-
if Enumerator.method_defined? :size
def test_find_in_batches_should_return_a_sized_enumerator
assert_equal 11, Post.find_in_batches(:batch_size => 1).size
assert_equal 6, Post.find_in_batches(:batch_size => 2).size
- assert_equal 4, Post.find_in_batches(batch_size: 2, begin_at: 4).size
+ assert_equal 4, Post.find_in_batches(batch_size: 2, start: 4).size
assert_equal 4, Post.find_in_batches(:batch_size => 3).size
assert_equal 1, Post.find_in_batches(:batch_size => 10_000).size
end
diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb
index 1e38b97c4a..cd9c76f1f0 100644
--- a/activerecord/test/cases/bind_parameter_test.rb
+++ b/activerecord/test/cases/bind_parameter_test.rb
@@ -39,7 +39,7 @@ module ActiveRecord
end
def test_binds_are_logged
- sub = @connection.substitute_at(@pk)
+ sub = Arel::Nodes::BindParam.new
binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
sql = "select * from topics where id = #{sub.to_sql}"
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index d09009b65d..8f2682c781 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -124,7 +124,7 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_should_generate_valid_sql_with_joins_and_group
- assert_nothing_raised ActiveRecord::StatementInvalid do
+ assert_nothing_raised do
AuditLog.joins(:developer).group(:id).count
end
end
@@ -545,8 +545,8 @@ class CalculationsTest < ActiveRecord::TestCase
assert_equal 7, Company.includes(:contracts).sum(:developer_id)
end
- def test_from_option_with_specified_index
- if Edge.connection.adapter_name == 'Mysql2'
+ if current_adapter?(:Mysql2Adapter)
+ def test_from_option_with_specified_index
assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
assert_equal Edge.where('sink_id < 5').count(:all),
Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
@@ -742,7 +742,7 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
- assert_nothing_raised ActiveRecord::StatementInvalid do
+ assert_nothing_raised do
developer = Developer.create!(name: 'developer')
developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count
end
diff --git a/activerecord/test/cases/collection_cache_key_test.rb b/activerecord/test/cases/collection_cache_key_test.rb
index 53058c5a4a..a2874438c1 100644
--- a/activerecord/test/cases/collection_cache_key_test.rb
+++ b/activerecord/test/cases/collection_cache_key_test.rb
@@ -66,5 +66,24 @@ module ActiveRecord
developers = projects(:active_record).developers
assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/, developers.cache_key)
end
+
+ test "cache_key for loaded collection with zero size" do
+ Comment.delete_all
+ posts = Post.includes(:comments)
+ empty_loaded_collection = posts.first.comments
+
+ assert_match(/\Acomments\/query-(\h+)-0\Z/, empty_loaded_collection.cache_key)
+ end
+
+ test "cache_key for queries with offset which return 0 rows" do
+ developers = Developer.offset(20)
+ assert_match(/\Adevelopers\/query-(\h+)-0\Z/, developers.cache_key)
+ end
+
+ test "cache_key with a relation having selected columns" do
+ developers = Developer.select(:salary)
+
+ assert_match(/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/, developers.cache_key)
+ end
end
end
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
index da0d7f5195..81162b7e98 100644
--- a/activerecord/test/cases/column_definition_test.rb
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -41,39 +41,49 @@ module ActiveRecord
if current_adapter?(:Mysql2Adapter)
def test_should_set_default_for_mysql_binary_data_types
type = SqlTypeMetadata.new(type: :binary, sql_type: "binary(1)")
- binary_column = AbstractMysqlAdapter::Column.new("title", "a", type)
+ binary_column = MySQL::Column.new("title", "a", type)
assert_equal "a", binary_column.default
type = SqlTypeMetadata.new(type: :binary, sql_type: "varbinary")
- varbinary_column = AbstractMysqlAdapter::Column.new("title", "a", type)
+ varbinary_column = MySQL::Column.new("title", "a", type)
assert_equal "a", varbinary_column.default
end
+ def test_should_be_empty_string_default_for_mysql_binary_data_types
+ type = SqlTypeMetadata.new(type: :binary, sql_type: "binary(1)")
+ binary_column = MySQL::Column.new("title", "", type, false)
+ assert_equal "", binary_column.default
+
+ type = SqlTypeMetadata.new(type: :binary, sql_type: "varbinary")
+ varbinary_column = MySQL::Column.new("title", "", type, false)
+ assert_equal "", varbinary_column.default
+ end
+
def test_should_not_set_default_for_blob_and_text_data_types
assert_raise ArgumentError do
- AbstractMysqlAdapter::Column.new("title", "a", SqlTypeMetadata.new(sql_type: "blob"))
+ MySQL::Column.new("title", "a", SqlTypeMetadata.new(sql_type: "blob"))
end
- text_type = AbstractMysqlAdapter::MysqlTypeMetadata.new(
+ text_type = MySQL::TypeMetadata.new(
SqlTypeMetadata.new(type: :text))
assert_raise ArgumentError do
- AbstractMysqlAdapter::Column.new("title", "Hello", text_type)
+ MySQL::Column.new("title", "Hello", text_type)
end
- text_column = AbstractMysqlAdapter::Column.new("title", nil, text_type)
+ text_column = MySQL::Column.new("title", nil, text_type)
assert_equal nil, text_column.default
- not_null_text_column = AbstractMysqlAdapter::Column.new("title", nil, text_type, false)
+ not_null_text_column = MySQL::Column.new("title", nil, text_type, false)
assert_equal "", not_null_text_column.default
end
def test_has_default_should_return_false_for_blob_and_text_data_types
binary_type = SqlTypeMetadata.new(sql_type: "blob")
- blob_column = AbstractMysqlAdapter::Column.new("title", nil, binary_type)
+ blob_column = MySQL::Column.new("title", nil, binary_type)
assert !blob_column.has_default?
text_type = SqlTypeMetadata.new(type: :text)
- text_column = AbstractMysqlAdapter::Column.new("title", nil, text_type)
+ text_column = MySQL::Column.new("title", nil, text_type)
assert !text_column.has_default?
end
end
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index 3c2f5d4219..358b6ad537 100644
--- a/activerecord/test/cases/connection_specification/resolver_test.rb
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -57,6 +57,12 @@ module ActiveRecord
"encoding" => "utf8" }, spec)
end
+ def test_url_missing_scheme
+ spec = resolve 'foo'
+ assert_equal({
+ "database" => "foo" }, spec)
+ end
+
def test_url_host_db
spec = resolve 'abstract://foo/bar?encoding=utf8'
assert_equal({
diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb
index 922cb59280..66b4c3f1ff 100644
--- a/activerecord/test/cases/counter_cache_test.rb
+++ b/activerecord/test/cases/counter_cache_test.rb
@@ -151,7 +151,7 @@ class CounterCacheTest < ActiveRecord::TestCase
test "reset the right counter if two have the same foreign key" do
michael = people(:michael)
- assert_nothing_raised(ActiveRecord::StatementInvalid) do
+ assert_nothing_raised do
Person.reset_counters(michael.id, :friends_too)
end
end
diff --git a/activerecord/test/cases/database_statements_test.rb b/activerecord/test/cases/database_statements_test.rb
index c689e97d83..ba085991e0 100644
--- a/activerecord/test/cases/database_statements_test.rb
+++ b/activerecord/test/cases/database_statements_test.rb
@@ -6,14 +6,23 @@ class DatabaseStatementsTest < ActiveRecord::TestCase
end
def test_insert_should_return_the_inserted_id
+ assert_not_nil return_the_inserted_id(method: :insert)
+ end
+
+ def test_create_should_return_the_inserted_id
+ assert_not_nil return_the_inserted_id(method: :create)
+ end
+
+ private
+
+ def return_the_inserted_id(method:)
# Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
if current_adapter?(:OracleAdapter)
sequence_name = "accounts_seq"
id_value = @connection.next_sequence_value(sequence_name)
- id = @connection.insert("INSERT INTO accounts (id, firm_id,credit_limit) VALUES (accounts_seq.nextval,42,5000)", nil, :id, id_value, sequence_name)
+ @connection.send(method, "INSERT INTO accounts (id, firm_id,credit_limit) VALUES (accounts_seq.nextval,42,5000)", nil, :id, id_value, sequence_name)
else
- id = @connection.insert("INSERT INTO accounts (firm_id,credit_limit) VALUES (42,5000)")
+ @connection.send(method, "INSERT INTO accounts (firm_id,credit_limit) VALUES (42,5000)")
end
- assert_not_nil id
end
end
diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb
index fb2d3bd497..067513e24c 100644
--- a/activerecord/test/cases/defaults_test.rb
+++ b/activerecord/test/cases/defaults_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'support/schema_dumping_helper'
require 'models/default'
require 'models/entrant'
@@ -80,7 +81,32 @@ class DefaultStringsTest < ActiveRecord::TestCase
end
end
+if current_adapter?(:PostgreSQLAdapter)
+ class PostgresqlDefaultExpressionTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ test "schema dump includes default expression" do
+ output = dump_table_schema("defaults")
+ assert_match %r/t\.date\s+"modified_date",\s+default: -> { "\('now'::text\)::date" }/, output
+ assert_match %r/t\.date\s+"modified_date_function",\s+default: -> { "now\(\)" }/, output
+ assert_match %r/t\.datetime\s+"modified_time",\s+default: -> { "now\(\)" }/, output
+ assert_match %r/t\.datetime\s+"modified_time_function",\s+default: -> { "now\(\)" }/, output
+ end
+ end
+end
+
if current_adapter?(:Mysql2Adapter)
+ class MysqlDefaultExpressionTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
+
+ if ActiveRecord::Base.connection.version >= '5.6.0'
+ test "schema dump includes default expression" do
+ output = dump_table_schema("datetime_defaults")
+ assert_match %r/t\.datetime\s+"modified_datetime",\s+default: -> { "CURRENT_TIMESTAMP" }/, output
+ end
+ end
+ end
+
class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase
# ActiveRecord::Base#create! (and #save and other related methods) will
# open a new transaction. When in transactional tests mode, this will
@@ -175,8 +201,7 @@ if current_adapter?(:Mysql2Adapter)
assert_equal '0', klass.columns_hash['zero'].default
assert !klass.columns_hash['zero'].null
- # 0 in MySQL 4, nil in 5.
- assert [0, nil].include?(klass.columns_hash['omit'].default)
+ assert_equal nil, klass.columns_hash['omit'].default
assert !klass.columns_hash['omit'].null
assert_raise(ActiveRecord::StatementInvalid) { klass.create! }
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index 7c930de97b..babacd1ee9 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -411,4 +411,14 @@ class EnumTest < ActiveRecord::TestCase
assert book.proposed?, "expected fixture to default to proposed status"
assert book.in_english?, "expected fixture to default to english language"
end
+
+ test "uses default value from database on initialization" do
+ book = Book.new
+ assert book.proposed?
+ end
+
+ test "uses default value from database on initialization when using custom mapping" do
+ book = Book.new
+ assert book.hard?
+ end
end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 9f90ab79a1..3e31874455 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -19,7 +19,7 @@ require 'models/car'
require 'models/tyre'
class FinderTest < ActiveRecord::TestCase
- fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations, :cars
+ fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :author_addresses, :customers, :categories, :categorizations, :cars
def test_find_by_id_with_hash
assert_raises(ActiveRecord::StatementInvalid) do
@@ -43,7 +43,7 @@ class FinderTest < ActiveRecord::TestCase
end
assert_equal "should happen", exception.message
- assert_nothing_raised(RuntimeError) do
+ assert_nothing_raised do
Topic.all.find(-> { raise "should not happen" }) { |e| e.title == topics(:first).title }
end
end
@@ -101,7 +101,7 @@ class FinderTest < ActiveRecord::TestCase
def test_find_with_ids_where_and_limit
# Please note that Topic 1 is the only not approved so
- # if it were among the first 3 it would raise a ActiveRecord::RecordNotFound
+ # if it were among the first 3 it would raise an ActiveRecord::RecordNotFound
records = Topic.where(approved: true).limit(3).find([3,2,5,1,4])
assert_equal 3, records.size
assert_equal 'The Third Topic of the day', records[0].title
@@ -516,16 +516,44 @@ class FinderTest < ActiveRecord::TestCase
assert_equal Topic.order("title").to_a.last(2), Topic.order("title").last(2)
end
- def test_last_with_integer_and_order_should_not_use_sql_limit
- query = assert_sql { Topic.order("title").last(5).entries }
- assert_equal 1, query.length
- assert_no_match(/LIMIT/, query.first)
+ def test_last_with_integer_and_order_should_use_sql_limit
+ relation = Topic.order("title")
+ assert_queries(1) { relation.last(5) }
+ assert !relation.loaded?
+ end
+
+ def test_last_with_integer_and_reorder_should_use_sql_limit
+ relation = Topic.reorder("title")
+ assert_queries(1) { relation.last(5) }
+ assert !relation.loaded?
+ end
+
+ def test_last_on_loaded_relation_should_not_use_sql
+ relation = Topic.limit(10).load
+ assert_no_queries do
+ relation.last
+ relation.last(2)
+ end
+ end
+
+ def test_last_with_irreversible_order
+ assert_deprecated do
+ Topic.order("coalesce(author_name, title)").last
+ end
end
- def test_last_with_integer_and_reorder_should_not_use_sql_limit
- query = assert_sql { Topic.reorder("title").last(5).entries }
- assert_equal 1, query.length
- assert_no_match(/LIMIT/, query.first)
+ def test_last_on_relation_with_limit_and_offset
+ post = posts('sti_comments')
+
+ comments = post.comments.order(id: :asc)
+ assert_equal comments.limit(2).to_a.last, comments.limit(2).last
+ assert_equal comments.limit(2).to_a.last(2), comments.limit(2).last(2)
+ assert_equal comments.limit(2).to_a.last(3), comments.limit(2).last(3)
+
+ comments = comments.offset(1)
+ assert_equal comments.limit(2).to_a.last, comments.limit(2).last
+ assert_equal comments.limit(2).to_a.last(2), comments.limit(2).last(2)
+ assert_equal comments.limit(2).to_a.last(3), comments.limit(2).last(3)
end
def test_take_and_first_and_last_with_integer_should_return_an_array
@@ -993,10 +1021,13 @@ class FinderTest < ActiveRecord::TestCase
end
def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
- assert_equal 2, Post.includes(authors: :author_address).order('author_addresses.id DESC ').limit(2).to_a.size
+ assert_equal 2, Post.includes(authors: :author_address).
+ where.not(author_addresses: { id: nil }).
+ order('author_addresses.id DESC').limit(2).to_a.size
assert_equal 3, Post.includes(author: :author_address, authors: :author_address).
- order('author_addresses_authors.id DESC ').limit(3).to_a.size
+ where.not(author_addresses_authors: { id: nil }).
+ order('author_addresses_authors.id DESC').limit(3).to_a.size
end
def test_find_with_nil_inside_set_passed_for_one_attribute
@@ -1055,7 +1086,7 @@ class FinderTest < ActiveRecord::TestCase
end
def test_finder_with_offset_string
- assert_nothing_raised(ActiveRecord::StatementInvalid) { Topic.offset("3").to_a }
+ assert_nothing_raised { Topic.offset("3").to_a }
end
test "find_by with hash conditions returns the first matching record" do
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index c73958900b..da934ab8fe 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -223,6 +223,10 @@ class FixturesTest < ActiveRecord::TestCase
assert_equal(%(table "parrots" has no column named "arrr".), e.message)
end
+ def test_yaml_file_with_symbol_columns
+ ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/naked/yml", "trees")
+ end
+
def test_omap_fixtures
assert_nothing_raised do
fixtures = ActiveRecord::FixtureSet.new(Account.connection, 'categories', Category, FIXTURES_ROOT + "/categories_ordered")
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 03bce547da..7da6842047 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -7,6 +7,7 @@ require 'models/project'
require 'models/subscriber'
require 'models/vegetables'
require 'models/shop'
+require 'models/sponsor'
module InheritanceTestHelper
def with_store_full_sti_class(&block)
@@ -492,6 +493,10 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
assert_equal 'Firm', firm.type
assert_instance_of Firm, firm
+ client = Client.new
+ assert_equal 'Client', client.type
+ assert_instance_of Client, client
+
firm = Company.new(type: 'Client') # overwrite the default type
assert_equal 'Client', firm.type
assert_instance_of Client, firm
@@ -524,3 +529,78 @@ class InheritanceAttributeTest < ActiveRecord::TestCase
assert_instance_of Empire, empire
end
end
+
+class InheritanceAttributeMappingTest < ActiveRecord::TestCase
+ setup do
+ @old_registry = ActiveRecord::Type.registry
+ ActiveRecord::Type.registry = ActiveRecord::Type::AdapterSpecificRegistry.new
+ ActiveRecord::Type.register :omg_sti, InheritanceAttributeMappingTest::OmgStiType
+ Company.delete_all
+ Sponsor.delete_all
+ end
+
+ teardown do
+ ActiveRecord::Type.registry = @old_registry
+ end
+
+ class OmgStiType < ActiveRecord::Type::String
+ def cast_value(value)
+ if value =~ /\Aomg_(.+)\z/
+ $1.classify
+ else
+ value
+ end
+ end
+
+ def serialize(value)
+ if value
+ "omg_%s" % value.underscore
+ end
+ end
+ end
+
+ class Company < ActiveRecord::Base
+ self.table_name = 'companies'
+ attribute :type, :omg_sti
+ end
+
+ class Startup < Company; end
+ class Empire < Company; end
+
+ class Sponsor < ActiveRecord::Base
+ self.table_name = 'sponsors'
+ attribute :sponsorable_type, :omg_sti
+
+ belongs_to :sponsorable, polymorphic: true
+ end
+
+ def test_sti_with_custom_type
+ Startup.create! name: 'a Startup'
+ Empire.create! name: 'an Empire'
+
+ assert_equal [["a Startup", "omg_inheritance_attribute_mapping_test/startup"],
+ ["an Empire", "omg_inheritance_attribute_mapping_test/empire"]], ActiveRecord::Base.connection.select_rows('SELECT name, type FROM companies').sort
+ assert_equal [["a Startup", "InheritanceAttributeMappingTest::Startup"],
+ ["an Empire", "InheritanceAttributeMappingTest::Empire"]], Company.all.map { |a| [a.name, a.type] }.sort
+
+ startup = Startup.first
+ startup.becomes! Empire
+ startup.save!
+
+ assert_equal [["a Startup", "omg_inheritance_attribute_mapping_test/empire"],
+ ["an Empire", "omg_inheritance_attribute_mapping_test/empire"]], ActiveRecord::Base.connection.select_rows('SELECT name, type FROM companies').sort
+
+ assert_equal [["a Startup", "InheritanceAttributeMappingTest::Empire"],
+ ["an Empire", "InheritanceAttributeMappingTest::Empire"]], Company.all.map { |a| [a.name, a.type] }.sort
+ end
+
+ def test_polymorphic_associations_custom_type
+ startup = Startup.create! name: 'a Startup'
+ sponsor = Sponsor.create! sponsorable: startup
+
+ assert_equal ["omg_inheritance_attribute_mapping_test/company"], ActiveRecord::Base.connection.select_values('SELECT sponsorable_type FROM sponsors')
+
+ sponsor = Sponsor.first
+ assert_equal startup, sponsor.sponsorable
+ end
+end
diff --git a/activerecord/test/cases/invalid_connection_test.rb b/activerecord/test/cases/invalid_connection_test.rb
index c26623e3ca..a16b52751a 100644
--- a/activerecord/test/cases/invalid_connection_test.rb
+++ b/activerecord/test/cases/invalid_connection_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
+if current_adapter?(:Mysql2Adapter)
class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
self.use_transactional_tests = false
@@ -20,3 +21,4 @@ class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
assert_equal "#{Bird.name} (call '#{Bird.name}.connection' to establish a connection)", Bird.inspect
end
end
+end
diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb
index d0940b3937..c7a1b81a75 100644
--- a/activerecord/test/cases/migration/column_attributes_test.rb
+++ b/activerecord/test/cases/migration/column_attributes_test.rb
@@ -63,8 +63,6 @@ module ActiveRecord
# 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
diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb
index 267d2fcccc..60ca90464d 100644
--- a/activerecord/test/cases/migration/compatibility_test.rb
+++ b/activerecord/test/cases/migration/compatibility_test.rb
@@ -21,6 +21,7 @@ module ActiveRecord
teardown do
connection.drop_table :testings rescue nil
ActiveRecord::Migration.verbose = @verbose_was
+ ActiveRecord::SchemaMigration.delete_all rescue nil
end
def test_migration_doesnt_remove_named_index
@@ -37,6 +38,81 @@ module ActiveRecord
assert_raise(StandardError) { ActiveRecord::Migrator.new(:up, [migration]).migrate }
assert connection.index_exists?(:testings, :foo, name: "custom_index_name")
end
+
+ def test_migration_does_remove_unnamed_index
+ connection.add_index :testings, :bar
+
+ migration = Class.new(ActiveRecord::Migration[4.2]) {
+ def version; 101 end
+ def migrate(x)
+ remove_index :testings, :bar
+ end
+ }.new
+
+ assert connection.index_exists?(:testings, :bar)
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+ assert_not connection.index_exists?(:testings, :bar)
+ end
+
+ def test_references_does_not_add_index_by_default
+ migration = Class.new(ActiveRecord::Migration) {
+ def migrate(x)
+ create_table :more_testings do |t|
+ t.references :foo
+ t.belongs_to :bar, index: false
+ end
+ end
+ }.new
+
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+
+ assert_not connection.index_exists?(:more_testings, :foo_id)
+ assert_not connection.index_exists?(:more_testings, :bar_id)
+ ensure
+ connection.drop_table :more_testings rescue nil
+ end
+
+ def test_timestamps_have_null_constraints_if_not_present_in_migration_of_create_table
+ migration = Class.new(ActiveRecord::Migration) {
+ def migrate(x)
+ create_table :more_testings do |t|
+ t.timestamps
+ end
+ end
+ }.new
+
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+
+ assert connection.columns(:more_testings).find { |c| c.name == 'created_at' }.null
+ assert connection.columns(:more_testings).find { |c| c.name == 'updated_at' }.null
+ ensure
+ connection.drop_table :more_testings rescue nil
+ end
+
+ def test_timestamps_have_null_constraints_if_not_present_in_migration_for_adding_timestamps_to_existing_table
+ migration = Class.new(ActiveRecord::Migration) {
+ def migrate(x)
+ add_timestamps :testings
+ end
+ }.new
+
+ ActiveRecord::Migrator.new(:up, [migration]).migrate
+
+ assert connection.columns(:testings).find { |c| c.name == 'created_at' }.null
+ assert connection.columns(:testings).find { |c| c.name == 'updated_at' }.null
+ end
+
+ def test_legacy_migrations_get_deprecation_warning_when_run
+ migration = Class.new(ActiveRecord::Migration) {
+ def up
+ add_column :testings, :baz, :string
+ end
+ }
+
+ assert_deprecated do
+ migration.migrate :up
+ end
+ end
end
end
end
diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb
index edbc8abe4d..85435f4dbc 100644
--- a/activerecord/test/cases/migration/references_foreign_key_test.rb
+++ b/activerecord/test/cases/migration/references_foreign_key_test.rb
@@ -32,10 +32,10 @@ module ActiveRecord
assert_equal [], @connection.foreign_keys("testings")
end
- test "foreign keys can be created in one query" do
+ test "foreign keys can be created in one query when index is not added" do
assert_queries(1) do
@connection.create_table :testings do |t|
- t.references :testing_parent, foreign_key: true
+ t.references :testing_parent, foreign_key: true, index: false
end
end
end
@@ -144,6 +144,22 @@ module ActiveRecord
@connection.drop_table "testing", if_exists: true
end
end
+
+ test "multiple foreign keys can be added to the same table" do
+ @connection.create_table :testings do |t|
+ t.integer :col_1
+ t.integer :col_2
+
+ t.foreign_key :testing_parents, column: :col_1
+ t.foreign_key :testing_parents, column: :col_2
+ end
+
+ fks = @connection.foreign_keys("testings")
+
+ fk_definitions = fks.map {|fk| [fk.from_table, fk.to_table, fk.column] }
+ assert_equal([["testings", "testing_parents", "col_1"],
+ ["testings", "testing_parents", "col_2"]], fk_definitions)
+ end
end
end
end
diff --git a/activerecord/test/cases/migration/references_index_test.rb b/activerecord/test/cases/migration/references_index_test.rb
index ad6b828d0b..a9a7f0f4c4 100644
--- a/activerecord/test/cases/migration/references_index_test.rb
+++ b/activerecord/test/cases/migration/references_index_test.rb
@@ -23,12 +23,12 @@ module ActiveRecord
assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
- def test_does_not_create_index
+ def test_creates_index_by_default_even_if_index_option_is_not_passed
connection.create_table table_name do |t|
t.references :foo
end
- assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_does_not_create_index_explicit
@@ -68,13 +68,13 @@ module ActiveRecord
assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
- def test_does_not_create_index_for_existing_table
+ def test_creates_index_for_existing_table_even_if_index_option_is_not_passed
connection.create_table table_name
connection.change_table table_name do |t|
t.references :foo
end
- assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_does_not_create_index_for_existing_table_explicit
diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb
index f613fd66c3..b9ce6bbc55 100644
--- a/activerecord/test/cases/migration/references_statements_test.rb
+++ b/activerecord/test/cases/migration/references_statements_test.rb
@@ -30,14 +30,14 @@ module ActiveRecord
assert column_exists?(table_name, :taggable_type, :string)
end
- def test_creates_reference_id_index
- add_reference table_name, :user, index: true
- assert index_exists?(table_name, :user_id)
+ def test_does_not_create_reference_id_index_if_index_is_false
+ add_reference table_name, :user, index: false
+ assert_not index_exists?(table_name, :user_id)
end
- def test_does_not_create_reference_id_index
+ def test_create_reference_id_index_even_if_index_option_is_passed
add_reference table_name, :user
- assert_not index_exists?(table_name, :user_id)
+ assert index_exists?(table_name, :user_id)
end
def test_creates_polymorphic_index
diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb
index 8eb027d53f..b926a92849 100644
--- a/activerecord/test/cases/migration/rename_table_test.rb
+++ b/activerecord/test/cases/migration/rename_table_test.rb
@@ -80,12 +80,10 @@ module ActiveRecord
end
def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences
- enable_extension!('uuid-ossp', connection)
connection.create_table :cats, id: :uuid
assert_nothing_raised { rename_table :cats, :felines }
ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines }
ensure
- disable_extension!('uuid-ossp', connection)
connection.drop_table :cats, if_exists: true
connection.drop_table :felines, if_exists: true
end
diff --git a/activerecord/test/cases/migration/table_and_index_test.rb b/activerecord/test/cases/migration/table_and_index_test.rb
deleted file mode 100644
index 24cba84a09..0000000000
--- a/activerecord/test/cases/migration/table_and_index_test.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require "cases/helper"
-
-module ActiveRecord
- class Migration
- class TableAndIndexTest < ActiveRecord::TestCase
- def test_add_schema_info_respects_prefix_and_suffix
- conn = ActiveRecord::Base.connection
-
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name, if_exists: true)
- # Use shorter prefix and suffix as in Oracle database identifier cannot be larger than 30 characters
- ActiveRecord::Base.table_name_prefix = 'p_'
- ActiveRecord::Base.table_name_suffix = '_s'
- conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name, if_exists: true)
-
- conn.initialize_schema_migrations_table
-
- assert_equal "p_unique_schema_migrations_s", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
- ensure
- ActiveRecord::Base.table_name_prefix = ""
- ActiveRecord::Base.table_name_suffix = ""
- end
- end
- end
-end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index b5b241ad1a..6a6250eec3 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -192,8 +192,6 @@ class MigrationTest < ActiveRecord::TestCase
# of 0, they take on the compile-time limit for precision and scale,
# so the following should succeed unless you have used really wacky
# compilation options
- # - SQLite2 has the default behavior of preserving all data sent in,
- # so this happens there too
assert_kind_of BigDecimal, b.value_of_e
assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
elsif current_adapter?(:SQLite3Adapter)
@@ -301,7 +299,7 @@ class MigrationTest < ActiveRecord::TestCase
e = assert_raise(StandardError) { migrator.run }
- assert_equal "An error has occurred, this migration was canceled:\n\nSomething broke", e.message
+ assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
assert_no_column Person, :last_name,
"On error, the Migrator should revert schema changes but it did not."
@@ -354,6 +352,93 @@ class MigrationTest < ActiveRecord::TestCase
Reminder.reset_table_name
end
+ def test_internal_metadata_table_name
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
+
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.table_name_prefix = "p_"
+ ActiveRecord::Base.table_name_suffix = "_s"
+ Reminder.reset_table_name
+ assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.internal_metadata_table_name = "changed"
+ Reminder.reset_table_name
+ assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
+ ActiveRecord::Base.table_name_prefix = ""
+ ActiveRecord::Base.table_name_suffix = ""
+ Reminder.reset_table_name
+ assert_equal "changed", ActiveRecord::InternalMetadata.table_name
+ ensure
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
+ Reminder.reset_table_name
+ end
+
+ def test_internal_metadata_stores_environment
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ old_path = ActiveRecord::Migrator.migrations_paths
+ ActiveRecord::Migrator.migrations_paths = migrations_path
+
+ ActiveRecord::Migrator.up(migrations_path)
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
+
+ original_rails_env = ENV["RAILS_ENV"]
+ original_rack_env = ENV["RACK_ENV"]
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+
+ refute_equal current_env, new_env
+
+ sleep 1 # mysql by default does not store fractional seconds in the database
+ ActiveRecord::Migrator.up(migrations_path)
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
+ ensure
+ ActiveRecord::Migrator.migrations_paths = old_path
+ ENV["RAILS_ENV"] = original_rails_env
+ ENV["RACK_ENV"] = original_rack_env
+ end
+
+
+ def test_migration_sets_internal_metadata_even_when_fully_migrated
+ current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ old_path = ActiveRecord::Migrator.migrations_paths
+ ActiveRecord::Migrator.migrations_paths = migrations_path
+
+ ActiveRecord::Migrator.up(migrations_path)
+ assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
+
+ original_rails_env = ENV["RAILS_ENV"]
+ original_rack_env = ENV["RACK_ENV"]
+ ENV["RAILS_ENV"] = ENV["RACK_ENV"] = "foofoo"
+ new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+
+ refute_equal current_env, new_env
+
+ sleep 1 # mysql by default does not store fractional seconds in the database
+
+ ActiveRecord::Migrator.up(migrations_path)
+ assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
+ ensure
+ ActiveRecord::Migrator.migrations_paths = old_path
+ ENV["RAILS_ENV"] = original_rails_env
+ ENV["RACK_ENV"] = original_rack_env
+ end
+
+ def test_rename_internal_metadata_table
+ original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
+
+ ActiveRecord::Base.internal_metadata_table_name = "active_record_internal_metadatas"
+ Reminder.reset_table_name
+
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
+ Reminder.reset_table_name
+
+ assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
+ ensure
+ ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
+ Reminder.reset_table_name
+ end
+
def test_proper_table_name_on_migration
reminder_class = new_isolated_reminder_class
migration = ActiveRecord::Migration.new
@@ -431,13 +516,12 @@ class MigrationTest < ActiveRecord::TestCase
data_column = columns.detect { |c| c.name == "data" }
assert_nil data_column.default
-
+ ensure
Person.connection.drop_table :binary_testings, if_exists: true
end
unless mysql_enforcing_gtid_consistency?
def test_create_table_with_query
- Person.connection.drop_table :table_from_query_testings rescue nil
Person.connection.create_table(:person, force: true)
Person.connection.create_table :table_from_query_testings, as: "SELECT id FROM person"
@@ -445,12 +529,11 @@ class MigrationTest < ActiveRecord::TestCase
columns = Person.connection.columns(:table_from_query_testings)
assert_equal 1, columns.length
assert_equal "id", columns.first.name
-
+ ensure
Person.connection.drop_table :table_from_query_testings rescue nil
end
def test_create_table_with_query_from_relation
- Person.connection.drop_table :table_from_query_testings rescue nil
Person.connection.create_table(:person, force: true)
Person.connection.create_table :table_from_query_testings, as: Person.select(:id)
@@ -458,7 +541,7 @@ class MigrationTest < ActiveRecord::TestCase
columns = Person.connection.columns(:table_from_query_testings)
assert_equal 1, columns.length
assert_equal "id", columns.first.name
-
+ ensure
Person.connection.drop_table :table_from_query_testings rescue nil
end
end
@@ -501,8 +584,7 @@ class MigrationTest < ActiveRecord::TestCase
end
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
- def test_out_of_range_limit_should_raise
- Person.connection.drop_table :test_limits rescue nil
+ def test_out_of_range_integer_limit_should_raise
e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
Person.connection.create_table :test_integer_limits, :force => true do |t|
t.column :bigone, :integer, :limit => 10
@@ -510,16 +592,22 @@ class MigrationTest < ActiveRecord::TestCase
end
assert_match(/No integer type has byte size 10/, e.message)
+ ensure
+ Person.connection.drop_table :test_integer_limits, if_exists: true
+ end
+ end
- unless current_adapter?(:PostgreSQLAdapter)
- assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
- Person.connection.create_table :test_text_limits, :force => true do |t|
- t.column :bigtext, :text, :limit => 0xfffffffff
- end
+ if current_adapter?(:Mysql2Adapter)
+ def test_out_of_range_text_limit_should_raise
+ e = assert_raise(ActiveRecord::ActiveRecordError, "text limit didn't raise") do
+ Person.connection.create_table :test_text_limits, force: true do |t|
+ t.text :bigtext, limit: 0xfffffffff
end
end
- Person.connection.drop_table :test_limits rescue nil
+ assert_match(/No text type has byte length #{0xfffffffff}/, e.message)
+ ensure
+ Person.connection.drop_table :test_text_limits, if_exists: true
end
end
@@ -641,7 +729,7 @@ class ReservedWordsMigrationTest < ActiveRecord::TestCase
connection.add_index :values, :value
connection.remove_index :values, :column => :value
end
-
+ ensure
connection.drop_table :values rescue nil
end
end
@@ -653,11 +741,11 @@ class ExplicitlyNamedIndexMigrationTest < ActiveRecord::TestCase
t.integer :value
end
- assert_nothing_raised ArgumentError do
+ assert_nothing_raised do
connection.add_index :values, :value, name: 'a_different_name'
connection.remove_index :values, column: :value, name: 'a_different_name'
end
-
+ ensure
connection.drop_table :values rescue nil
end
end
diff --git a/activerecord/test/cases/modules_test.rb b/activerecord/test/cases/modules_test.rb
index 7f31325f47..486bcc22df 100644
--- a/activerecord/test/cases/modules_test.rb
+++ b/activerecord/test/cases/modules_test.rb
@@ -63,7 +63,7 @@ class ModulesTest < ActiveRecord::TestCase
def test_assign_ids
firm = MyApplication::Business::Firm.first
- assert_nothing_raised NameError, "Should be able to resolve all class constants via reflection" do
+ assert_nothing_raised do
firm.client_ids = [MyApplication::Business::Client.first.id]
end
end
@@ -72,7 +72,7 @@ class ModulesTest < ActiveRecord::TestCase
def test_eager_loading_in_modules
clients = []
- assert_nothing_raised NameError, "Should be able to resolve all class constants via reflection" do
+ assert_nothing_raised do
clients << MyApplication::Business::Client.references(:accounts).merge!(:includes => {:firm => :account}, :where => 'accounts.id IS NOT NULL').find(3)
clients << MyApplication::Business::Client.includes(:firm => :account).find(3)
end
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index 39cdcf5403..af4183a601 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -104,7 +104,7 @@ class MultipleDbTest < ActiveRecord::TestCase
def test_associations_should_work_when_model_has_no_connection
begin
ActiveRecord::Base.remove_connection
- assert_nothing_raised ActiveRecord::ConnectionNotEstablished do
+ assert_nothing_raised do
College.first.courses.first
end
ensure
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 0b700afcb4..11fb164d50 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -61,6 +61,13 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
assert_equal "No association found for name `honesty'. Has it been defined yet?", exception.message
end
+ def test_should_raise_an_UnknownAttributeError_for_non_existing_nested_attributes
+ exception = assert_raise ActiveModel::UnknownAttributeError do
+ Pirate.new(:ship_attributes => { :sail => true })
+ end
+ assert_equal "unknown attribute 'sail' for Ship.", exception.message
+ end
+
def test_should_disable_allow_destroy_by_default
Pirate.accepts_nested_attributes_for :ship
@@ -69,7 +76,7 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
pirate.update(ship_attributes: { '_destroy' => true, :id => ship.id })
- assert_nothing_raised(ActiveRecord::RecordNotFound) { pirate.ship.reload }
+ assert_nothing_raised { pirate.ship.reload }
end
def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction
@@ -146,6 +153,19 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
assert man.reload.interests.empty?
end
+ def test_reject_if_is_not_short_circuited_if_allow_destroy_is_false
+ Pirate.accepts_nested_attributes_for :ship, reject_if: ->(a) { a[:name] == "The Golden Hind" }, allow_destroy: false
+
+ pirate = Pirate.create!(catchphrase: "Stop wastin' me time", ship_attributes: { name: "White Pearl", _destroy: "1" })
+ assert_equal "White Pearl", pirate.reload.ship.name
+
+ pirate.update!(ship_attributes: { id: pirate.ship.id, name: "The Golden Hind", _destroy: "1" })
+ assert_equal "White Pearl", pirate.reload.ship.name
+
+ pirate.update!(ship_attributes: { id: pirate.ship.id, name: "Black Pearl", _destroy: "1" })
+ assert_equal "Black Pearl", pirate.reload.ship.name
+ end
+
def test_has_many_association_updating_a_single_record
Man.accepts_nested_attributes_for(:interests)
man = Man.create(name: 'John')
@@ -160,7 +180,7 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
pirate.ship_attributes = { :id => "" }
- assert_nothing_raised(ActiveRecord::RecordNotFound) { pirate.save! }
+ assert_nothing_raised { pirate.save! }
end
def test_first_and_array_index_zero_methods_return_the_same_value_when_nested_attributes_are_set_to_update_existing_record
@@ -491,7 +511,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
[nil, '0', 0, 'false', false].each do |not_truth|
@ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: not_truth })
- assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload }
+ assert_nothing_raised { @ship.pirate.reload }
end
end
@@ -499,7 +519,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc(&:empty?)
@ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: '1' })
- assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload }
+ assert_nothing_raised { @ship.pirate.reload }
ensure
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc(&:empty?)
end
@@ -516,7 +536,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
pirate = @ship.pirate
@ship.attributes = { :pirate_attributes => { :id => pirate.id, '_destroy' => true } }
- assert_nothing_raised(ActiveRecord::RecordNotFound) { Pirate.find(pirate.id) }
+ assert_nothing_raised { Pirate.find(pirate.id) }
@ship.save
assert_raise(ActiveRecord::RecordNotFound) { Pirate.find(pirate.id) }
end
@@ -569,6 +589,13 @@ module NestedAttributesOnACollectionAssociationTests
assert_respond_to @pirate, association_setter
end
+ def test_should_raise_an_UnknownAttributeError_for_non_existing_nested_attributes_for_has_many
+ exception = assert_raise ActiveModel::UnknownAttributeError do
+ @pirate.parrots_attributes = [{ peg_leg: true }]
+ end
+ assert_equal "unknown attribute 'peg_leg' for Parrot.", exception.message
+ end
+
def test_should_save_only_one_association_on_create
pirate = Pirate.create!({
:catchphrase => 'Arr',
@@ -686,7 +713,7 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_not_assign_destroy_key_to_a_record
- assert_nothing_raised ActiveRecord::UnknownAttributeError do
+ assert_nothing_raised do
@pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
end
end
@@ -721,8 +748,8 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_raise_an_argument_error_if_something_else_than_a_hash_is_passed
- assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, {}) }
- assert_nothing_raised(ArgumentError) { @pirate.send(association_setter, Hash.new) }
+ assert_nothing_raised { @pirate.send(association_setter, {}) }
+ assert_nothing_raised { @pirate.send(association_setter, Hash.new) }
exception = assert_raise ArgumentError do
@pirate.send(association_setter, "foo")
@@ -797,7 +824,7 @@ module NestedAttributesOnACollectionAssociationTests
def test_can_use_symbols_as_object_identifier
@pirate.attributes = { :parrots_attributes => { :foo => { :name => 'Lovely Day' }, :bar => { :name => 'Blown Away' } } }
- assert_nothing_raised(NoMethodError) { @pirate.save! }
+ assert_nothing_raised { @pirate.save! }
end
def test_numeric_column_changes_from_zero_to_no_empty_string
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index af15e63d9c..56092aaa0c 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -183,7 +183,7 @@ class PersistenceTest < ActiveRecord::TestCase
end
end
- def test_dupd_becomes_persists_changes_from_the_original
+ def test_duped_becomes_persists_changes_from_the_original
original = topics(:first)
copy = original.dup.becomes(Reply)
copy.save!
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index 7e18313c00..e27a747730 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -130,27 +130,25 @@ class PrimaryKeysTest < ActiveRecord::TestCase
end
def test_supports_primary_key
- assert_nothing_raised NoMethodError do
+ assert_nothing_raised do
ActiveRecord::Base.connection.supports_primary_key?
end
end
- def test_primary_key_returns_value_if_it_exists
- klass = Class.new(ActiveRecord::Base) do
- self.table_name = 'developers'
- end
+ if ActiveRecord::Base.connection.supports_primary_key?
+ def test_primary_key_returns_value_if_it_exists
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = 'developers'
+ end
- if ActiveRecord::Base.connection.supports_primary_key?
assert_equal 'id', klass.primary_key
end
- end
- def test_primary_key_returns_nil_if_it_does_not_exist
- klass = Class.new(ActiveRecord::Base) do
- self.table_name = 'developers_projects'
- end
+ def test_primary_key_returns_nil_if_it_does_not_exist
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = 'developers_projects'
+ end
- if ActiveRecord::Base.connection.supports_primary_key?
assert_nil klass.primary_key
end
end
@@ -262,6 +260,13 @@ class CompositePrimaryKeyTest < ActiveRecord::TestCase
assert_equal ["region", "code"], @connection.primary_keys("barcodes")
end
+ def test_primary_key_issues_warning
+ warning = capture(:stderr) do
+ assert_nil @connection.primary_key("barcodes")
+ end
+ assert_match(/WARNING: Rails does not support composite primary key\./, warning)
+ end
+
def test_collectly_dump_composite_primary_key
schema = dump_table_schema "barcodes"
assert_match %r{create_table "barcodes", primary_key: \["region", "code"\]}, schema
diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb
index 9c04a41e69..710c86b151 100644
--- a/activerecord/test/cases/reflection_test.rb
+++ b/activerecord/test/cases/reflection_test.rb
@@ -23,6 +23,7 @@ require 'models/chef'
require 'models/department'
require 'models/cake_designer'
require 'models/drink_designer'
+require 'models/mocktail_designer'
require 'models/recipe'
class ReflectionTest < ActiveRecord::TestCase
@@ -278,6 +279,15 @@ class ReflectionTest < ActiveRecord::TestCase
assert_equal 2, @hotel.chefs.size
end
+ def test_scope_chain_does_not_interfere_with_hmt_with_polymorphic_case_and_sti
+ @hotel = Hotel.create!
+ @hotel.mocktail_designers << MocktailDesigner.create!
+
+ assert_equal 1, @hotel.mocktail_designers.size
+ assert_equal 1, @hotel.mocktail_designers.count
+ assert_equal 1, @hotel.chef_lists.size
+ end
+
def test_scope_chain_of_polymorphic_association_does_not_leak_into_other_hmt_associations
hotel = Hotel.create!
department = hotel.departments.create!
diff --git a/activerecord/test/cases/relation/merging_test.rb b/activerecord/test/cases/relation/merging_test.rb
index 0a2e874e4f..60a806c05a 100644
--- a/activerecord/test/cases/relation/merging_test.rb
+++ b/activerecord/test/cases/relation/merging_test.rb
@@ -104,6 +104,13 @@ class RelationMergingTest < ActiveRecord::TestCase
post = PostThatLoadsCommentsInAnAfterSaveHook.create!(title: "First Post", body: "Blah blah blah.")
assert_equal "First comment!", post.comments.where(body: "First comment!").first_or_create.body
end
+
+ def test_merging_with_from_clause
+ relation = Post.all
+ assert relation.from_clause.empty?
+ relation = relation.merge(Post.from("posts"))
+ refute relation.from_clause.empty?
+ end
end
class MergingDifferentRelationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relation/mutation_test.rb b/activerecord/test/cases/relation/mutation_test.rb
index d0f60a84b5..ffb2da7a26 100644
--- a/activerecord/test/cases/relation/mutation_test.rb
+++ b/activerecord/test/cases/relation/mutation_test.rb
@@ -26,6 +26,10 @@ module ActiveRecord
def sanitize_sql_for_order(sql)
sql
end
+
+ def arel_attribute(name, table)
+ table[name]
+ end
end
def relation
diff --git a/activerecord/test/cases/relation/or_test.rb b/activerecord/test/cases/relation/or_test.rb
index 2006fc9611..ce8c5ca489 100644
--- a/activerecord/test/cases/relation/or_test.rb
+++ b/activerecord/test/cases/relation/or_test.rb
@@ -52,9 +52,11 @@ module ActiveRecord
end
def test_or_with_incompatible_relations
- assert_raises ArgumentError do
+ error = assert_raises ArgumentError do
Post.order('body asc').where('id = 1').or(Post.order('id desc').where(:id => [2, 3])).to_a
end
+
+ assert_equal "Relation passed to #or must be structurally compatible. Incompatible values: [:order]", error.message
end
def test_or_when_grouping
@@ -80,5 +82,11 @@ module ActiveRecord
assert_equal p.loaded?, true
assert_equal expected, p.or(Post.where('id = 2')).to_a
end
+
+ def test_or_with_non_relation_object_raises_error
+ assert_raises ArgumentError do
+ Post.where(id: [1, 2, 3]).or(title: 'Rails')
+ end
+ end
end
end
diff --git a/activerecord/test/cases/relation/record_fetch_warning_test.rb b/activerecord/test/cases/relation/record_fetch_warning_test.rb
index 62f0a7cc49..53daf436e5 100644
--- a/activerecord/test/cases/relation/record_fetch_warning_test.rb
+++ b/activerecord/test/cases/relation/record_fetch_warning_test.rb
@@ -7,7 +7,7 @@ module ActiveRecord
def test_warn_on_records_fetched_greater_than
original_logger = ActiveRecord::Base.logger
- orginal_warn_on_records_fetched_greater_than = ActiveRecord::Base.warn_on_records_fetched_greater_than
+ original_warn_on_records_fetched_greater_than = ActiveRecord::Base.warn_on_records_fetched_greater_than
log = StringIO.new
ActiveRecord::Base.logger = ActiveSupport::Logger.new(log)
@@ -22,7 +22,7 @@ module ActiveRecord
assert_match(/Query fetched/, log.string)
ensure
ActiveRecord::Base.logger = original_logger
- ActiveRecord::Base.warn_on_records_fetched_greater_than = orginal_warn_on_records_fetched_greater_than
+ ActiveRecord::Base.warn_on_records_fetched_greater_than = original_warn_on_records_fetched_greater_than
end
end
end
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index bc6378b90e..56a2b5b8c6 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require "models/author"
require "models/binary"
require "models/cake_designer"
+require "models/car"
require "models/chef"
require "models/comment"
require "models/edge"
@@ -14,7 +15,7 @@ require "models/vertex"
module ActiveRecord
class WhereTest < ActiveRecord::TestCase
- fixtures :posts, :edges, :authors, :binaries, :essays
+ fixtures :posts, :edges, :authors, :binaries, :essays, :cars, :treasures, :price_estimates
def test_where_copies_bind_params
author = authors(:david)
@@ -114,6 +115,17 @@ module ActiveRecord
assert_equal expected.to_sql, actual.to_sql
end
+ def test_polymorphic_array_where_multiple_types
+ treasure_1 = treasures(:diamond)
+ treasure_2 = treasures(:sapphire)
+ car = cars(:honda)
+
+ expected = [price_estimates(:diamond), price_estimates(:sapphire_1), price_estimates(:sapphire_2), price_estimates(:honda)].sort
+ actual = PriceEstimate.where(estimate_of: [treasure_1, treasure_2, car]).to_a.sort
+
+ assert_equal expected, actual
+ end
+
def test_polymorphic_nested_relation_where
expected = PriceEstimate.where(estimate_of_type: 'Treasure', estimate_of_id: Treasure.where(id: [1,2]))
actual = PriceEstimate.where(estimate_of: Treasure.where(id: [1,2]))
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index f46d414b95..03583344a8 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -43,13 +43,17 @@ module ActiveRecord
(Relation::SINGLE_VALUE_METHODS - [:create_with]).each do |method|
assert_nil relation.send("#{method}_value"), method.to_s
end
- assert_equal({}, relation.create_with_value)
+ value = relation.create_with_value
+ assert_equal({}, value)
+ assert_predicate value, :frozen?
end
def test_multi_value_initialize
relation = Relation.new(FakeKlass, :b, nil)
Relation::MULTI_VALUE_METHODS.each do |method|
- assert_equal [], relation.send("#{method}_values"), method.to_s
+ values = relation.send("#{method}_values")
+ assert_equal [], values, method.to_s
+ assert_predicate values, :frozen?, method.to_s
end
end
@@ -77,7 +81,6 @@ module ActiveRecord
def test_tree_is_not_traversed
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1
left = relation.table[:id].eq(10)
right = relation.table[:id].eq(10)
combine = left.and right
@@ -104,7 +107,6 @@ module ActiveRecord
def test_create_with_value_with_wheres
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
- # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1
relation.where! relation.table[:id].eq(10)
relation.create_with_value = {:hello => 'world'}
assert_equal({:hello => 'world', :id => 10}, relation.scope_for_create)
@@ -115,7 +117,6 @@ module ActiveRecord
relation = Relation.new(Post, Post.arel_table, Post.predicate_builder)
assert_equal({}, relation.scope_for_create)
- # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1
relation.where! relation.table[:id].eq(10)
assert_equal({}, relation.scope_for_create)
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 7149c7d072..95e4230a58 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -19,6 +19,7 @@ require 'models/aircraft'
require "models/possession"
require "models/reader"
require "models/categorization"
+require "models/edge"
class RelationTest < ActiveRecord::TestCase
fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
@@ -111,15 +112,38 @@ class RelationTest < ActiveRecord::TestCase
def test_loaded_first
topics = Topic.all.order('id ASC')
+ topics.to_a # force load
- assert_queries(1) do
- topics.to_a # force load
- 2.times { assert_equal "The First Topic", topics.first.title }
+ assert_no_queries do
+ assert_equal "The First Topic", topics.first.title
+ end
+
+ assert topics.loaded?
+ end
+
+ def test_loaded_first_with_limit
+ topics = Topic.all.order('id ASC')
+ topics.to_a # force load
+
+ assert_no_queries do
+ assert_equal ["The First Topic",
+ "The Second Topic of the day"], topics.first(2).map(&:title)
end
assert topics.loaded?
end
+ def test_first_get_more_than_available
+ topics = Topic.all.order('id ASC')
+ unloaded_first = topics.first(10)
+ topics.to_a # force load
+
+ assert_no_queries do
+ loaded_first = topics.first(10)
+ assert_equal unloaded_first, loaded_first
+ end
+ end
+
def test_reload
topics = Topic.all
@@ -200,6 +224,39 @@ class RelationTest < ActiveRecord::TestCase
assert_equal topics(:fifth).title, topics.first.title
end
+ def test_reverse_order_with_function
+ topics = Topic.order("length(title)").reverse_order
+ assert_equal topics(:second).title, topics.first.title
+ end
+
+ def test_reverse_order_with_function_other_predicates
+ topics = Topic.order("author_name, length(title), id").reverse_order
+ assert_equal topics(:second).title, topics.first.title
+ topics = Topic.order("length(author_name), id, length(title)").reverse_order
+ assert_equal topics(:fifth).title, topics.first.title
+ end
+
+ def test_reverse_order_with_multiargument_function
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order("concat(author_name, title)").reverse_order
+ end
+ end
+
+ def test_reverse_order_with_nulls_first_or_last
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order("title NULLS FIRST").reverse_order
+ end
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Topic.order("title nulls last").reverse_order
+ end
+ end
+
+ def test_default_reverse_order_on_table_without_primary_key
+ assert_raises(ActiveRecord::IrreversibleOrderError) do
+ Edge.all.reverse_order
+ end
+ end
+
def test_order_with_hash_and_symbol_generates_the_same_sql
assert_equal Topic.order(:id).to_sql, Topic.order(:id => :asc).to_sql
end
@@ -301,6 +358,12 @@ class RelationTest < ActiveRecord::TestCase
def test_finding_with_sanitized_order
query = Tag.order(["field(id, ?)", [1,3,2]]).to_sql
assert_match(/field\(id, 1,3,2\)/, query)
+
+ query = Tag.order(["field(id, ?)", []]).to_sql
+ assert_match(/field\(id, NULL\)/, query)
+
+ query = Tag.order(["field(id, ?)", nil]).to_sql
+ assert_match(/field\(id, NULL\)/, query)
end
def test_finding_with_order_limit_and_offset
@@ -1216,6 +1279,16 @@ class RelationTest < ActiveRecord::TestCase
assert posts.loaded?
end
+ def test_to_a_should_dup_target
+ posts = Post.all
+
+ original_size = posts.size
+ removed = posts.to_a.pop
+
+ assert_equal original_size, posts.size
+ assert_includes posts.to_a, removed
+ end
+
def test_build
posts = Post.all
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index a7735a2c7e..8def74e75b 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -38,6 +38,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{create_table "accounts"}, output
assert_match %r{create_table "authors"}, output
assert_no_match %r{create_table "schema_migrations"}, output
+ assert_no_match %r{create_table "ar_internal_metadata"}, output
end
def test_schema_dump_uses_force_cascade_on_create_table
@@ -158,6 +159,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_no_match %r{create_table "accounts"}, output
assert_match %r{create_table "authors"}, output
assert_no_match %r{create_table "schema_migrations"}, output
+ assert_no_match %r{create_table "ar_internal_metadata"}, output
end
def test_schema_dump_with_regexp_ignored_table
@@ -165,27 +167,28 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_no_match %r{create_table "accounts"}, output
assert_match %r{create_table "authors"}, output
assert_no_match %r{create_table "schema_migrations"}, output
+ assert_no_match %r{create_table "ar_internal_metadata"}, output
end
def test_schema_dumps_index_columns_in_right_order
- index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_index/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
- assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
else
- assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index"', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition
end
end
def test_schema_dumps_partial_indices
- index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_partial_index/).first.strip
+ index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
if current_adapter?(:PostgreSQLAdapter)
- assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
elsif current_adapter?(:Mysql2Adapter)
- assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
+ 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 't.index ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
else
- assert_equal 't.index ["firm_id", "type"], name: "company_partial_index"', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition
end
end
@@ -232,8 +235,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dumps_index_type
output = standard_dump
- assert_match %r{t\.index \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
- assert_match %r{t\.index \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
+ assert_match %r{add_index "key_tests", \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
+ assert_match %r{add_index "key_tests", \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
end
end
@@ -342,6 +345,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_no_match %r{create_table "foo_.+_bar"}, output
assert_no_match %r{add_index "foo_.+_bar"}, output
assert_no_match %r{create_table "schema_migrations"}, output
+ assert_no_match %r{create_table "ar_internal_metadata"}, output
if ActiveRecord::Base.connection.supports_foreign_keys?
assert_no_match %r{add_foreign_key "foo_.+_bar"}, output
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 86316ab476..c918cbdef5 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -374,6 +374,18 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal 10, DeveloperCalledJamis.unscoped { DeveloperCalledJamis.poor }.length
end
+ def test_default_scope_with_joins
+ assert_equal Comment.where(post_id: SpecialPostWithDefaultScope.pluck(:id)).count,
+ Comment.joins(:special_post_with_default_scope).count
+ assert_equal Comment.where(post_id: Post.pluck(:id)).count,
+ Comment.joins(:post).count
+ end
+
+ def test_unscoped_with_joins_should_not_have_default_scope
+ assert_equal SpecialPostWithDefaultScope.unscoped { Comment.joins(:special_post_with_default_scope).to_a },
+ Comment.joins(:post).to_a
+ end
+
def test_default_scope_select_ignored_by_aggregations
assert_equal DeveloperWithSelect.all.to_a.count, DeveloperWithSelect.count
end
@@ -459,4 +471,18 @@ class DefaultScopingTest < ActiveRecord::TestCase
scope = Bus.all
assert_equal scope.where_clause.ast.children.length, 1
end
+
+ def test_sti_conditions_are_not_carried_in_default_scope
+ ConditionalStiPost.create! body: ''
+ SubConditionalStiPost.create! body: ''
+ SubConditionalStiPost.create! title: 'Hello world', body: ''
+
+ assert_equal 2, ConditionalStiPost.count
+ assert_equal 2, ConditionalStiPost.all.to_a.size
+ assert_equal 3, ConditionalStiPost.unscope(where: :title).to_a.size
+
+ assert_equal 1, SubConditionalStiPost.count
+ assert_equal 1, SubConditionalStiPost.all.to_a.size
+ assert_equal 2, SubConditionalStiPost.unscope(where: :title).to_a.size
+ end
end
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 7a8eaeccb7..acba97bbb8 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -440,6 +440,25 @@ class NamedScopingTest < ActiveRecord::TestCase
end
end
+ def test_scopes_with_reserved_names
+ class << Topic
+ def public_method; end
+ public :public_method
+
+ def protected_method; end
+ protected :protected_method
+
+ def private_method; end
+ private :private_method
+ end
+
+ [:public_method, :protected_method, :private_method].each do |reserved_method|
+ assert Topic.respond_to?(reserved_method, true)
+ ActiveRecord::Base.logger.expects(:warn)
+ silence_warnings { Topic.scope(reserved_method, -> { }) }
+ end
+ end
+
def test_scopes_on_relations
# Topic.replied
approved_topics = Topic.all.approved.order('id DESC')
diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb
index 4bfffbe9c6..c15d57460b 100644
--- a/activerecord/test/cases/scoping/relation_scoping_test.rb
+++ b/activerecord/test/cases/scoping/relation_scoping_test.rb
@@ -209,9 +209,23 @@ class RelationScopingTest < ActiveRecord::TestCase
assert_not_equal [], Developer.all
end
- def test_current_scope_does_not_pollute_other_subclasses
- Post.none.scoping do
- assert StiPost.all.any?
+ def test_current_scope_does_not_pollute_sibling_subclasses
+ Comment.none.scoping do
+ assert_not SpecialComment.all.any?
+ assert_not VerySpecialComment.all.any?
+ assert_not SubSpecialComment.all.any?
+ end
+
+ SpecialComment.none.scoping do
+ assert Comment.all.any?
+ assert VerySpecialComment.all.any?
+ assert_not SubSpecialComment.all.any?
+ end
+
+ SubSpecialComment.none.scoping do
+ assert Comment.all.any?
+ assert VerySpecialComment.all.any?
+ assert SpecialComment.all.any?
end
end
end
diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb
index e9cdf94c99..bce86875e1 100644
--- a/activerecord/test/cases/store_test.rb
+++ b/activerecord/test/cases/store_test.rb
@@ -104,7 +104,7 @@ class StoreTest < ActiveRecord::TestCase
assert_equal true, user.settings.instance_of?(ActiveSupport::HashWithIndifferentAccess)
end
- test "convert store attributes from any format other than Hash or HashWithIndifferent access losing the data" do
+ test "convert store attributes from any format other than Hash or HashWithIndifferentAccess losing the data" do
@john.json_data = "somedata"
@john.height = 'low'
assert_equal true, @john.json_data.instance_of?(ActiveSupport::HashWithIndifferentAccess)
@@ -177,6 +177,7 @@ class StoreTest < ActiveRecord::TestCase
assert_equal [:color], first_model.stored_attributes[:data]
assert_equal [:color, :width, :height], second_model.stored_attributes[:data]
assert_equal [:color, :area, :volume], third_model.stored_attributes[:data]
+ assert_equal [:color], first_model.stored_attributes[:data]
end
test "YAML coder initializes the store when a Nil value is given" do
diff --git a/activerecord/test/cases/suppressor_test.rb b/activerecord/test/cases/suppressor_test.rb
index 72c5c16555..7d44e36419 100644
--- a/activerecord/test/cases/suppressor_test.rb
+++ b/activerecord/test/cases/suppressor_test.rb
@@ -46,7 +46,18 @@ class SuppressorTest < ActiveRecord::TestCase
Notification.suppress { UserWithNotification.create! }
assert_difference -> { Notification.count } do
- Notification.create!
+ Notification.create!(message: "New Comment")
+ end
+ end
+
+ def test_suppresses_validations_on_create
+ assert_no_difference -> { Notification.count } do
+ Notification.suppress do
+ User.create
+ User.create!
+ User.new.save
+ User.new.save!
+ end
end
end
end
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
index c8f4179313..49df6628eb 100644
--- a/activerecord/test/cases/tasks/database_tasks_test.rb
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -12,12 +12,39 @@ module ActiveRecord
end
ADAPTERS_TASKS = {
- mysql: :mysql_tasks,
mysql2: :mysql_tasks,
postgresql: :postgresql_tasks,
sqlite3: :sqlite_tasks
}
+ class DatabaseTasksUtilsTask< ActiveRecord::TestCase
+ def test_raises_an_error_when_called_with_protected_environment
+ ActiveRecord::Migrator.stubs(:current_version).returns(1)
+
+ protected_environments = ActiveRecord::Base.protected_environments.dup
+ current_env = ActiveRecord::Migrator.current_environment
+ assert !protected_environments.include?(current_env)
+ # Assert no error
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+
+ ActiveRecord::Base.protected_environments << current_env
+ assert_raise(ActiveRecord::ProtectedEnvironmentError) do
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+ end
+ ensure
+ ActiveRecord::Base.protected_environments = protected_environments
+ end
+
+ def test_raises_an_error_if_no_migrations_have_been_made
+ ActiveRecord::InternalMetadata.stubs(:table_exists?).returns(false)
+ ActiveRecord::Migrator.stubs(:current_version).returns(1)
+
+ assert_raise(ActiveRecord::NoEnvironmentInSchemaError) do
+ ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
+ end
+ end
+ end
+
class DatabaseTasksRegisterTask < ActiveRecord::TestCase
def test_register_task
klazz = Class.new do
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
index 7cc74f9d9f..1632f04854 100644
--- a/activerecord/test/cases/tasks/mysql_rake_test.rb
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -59,97 +59,94 @@ module ActiveRecord
end
end
- if current_adapter?(:MysqlAdapter)
- class MysqlDBCreateAsRootTest < ActiveRecord::TestCase
- def setup
- @connection = stub("Connection", create_database: true)
- @error = Mysql::Error.new "Invalid permissions"
- @configuration = {
- 'adapter' => 'mysql2',
- 'database' => 'my-app-db',
- 'username' => 'pat',
- 'password' => 'wossname'
- }
-
- $stdin.stubs(:gets).returns("secret\n")
- $stdout.stubs(:print).returns(nil)
- @error.stubs(:errno).returns(1045)
- ActiveRecord::Base.stubs(:connection).returns(@connection)
- ActiveRecord::Base.stubs(:establish_connection).
- raises(@error).
- then.returns(true)
- end
+ class MysqlDBCreateAsRootTest < ActiveRecord::TestCase
+ def setup
+ @connection = stub("Connection", create_database: true)
+ @error = Mysql2::Error.new("Invalid permissions")
+ @configuration = {
+ 'adapter' => 'mysql2',
+ 'database' => 'my-app-db',
+ 'username' => 'pat',
+ 'password' => 'wossname'
+ }
- if defined?(::Mysql)
- def test_root_password_is_requested
- assert_permissions_granted_for "pat"
- $stdin.expects(:gets).returns("secret\n")
+ $stdin.stubs(:gets).returns("secret\n")
+ $stdout.stubs(:print).returns(nil)
+ @error.stubs(:errno).returns(1045)
+ ActiveRecord::Base.stubs(:connection).returns(@connection)
+ ActiveRecord::Base.stubs(:establish_connection).
+ raises(@error).
+ then.returns(true)
+ end
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
- end
+ def test_root_password_is_requested
+ assert_permissions_granted_for("pat")
+ $stdin.expects(:gets).returns("secret\n")
- def test_connection_established_as_root
- assert_permissions_granted_for "pat"
- ActiveRecord::Base.expects(:establish_connection).with(
- 'adapter' => 'mysql2',
- 'database' => nil,
- 'username' => 'root',
- 'password' => 'secret'
- )
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ def test_connection_established_as_root
+ assert_permissions_granted_for("pat")
+ ActiveRecord::Base.expects(:establish_connection).with(
+ 'adapter' => 'mysql2',
+ 'database' => nil,
+ 'username' => 'root',
+ 'password' => 'secret'
+ )
- def test_database_created_by_root
- assert_permissions_granted_for "pat"
- @connection.expects(:create_database).
- with('my-app-db', {})
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ def test_database_created_by_root
+ assert_permissions_granted_for("pat")
+ @connection.expects(:create_database).
+ with('my-app-db', {})
- def test_grant_privileges_for_normal_user
- assert_permissions_granted_for "pat"
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- def test_do_not_grant_privileges_for_root_user
- @configuration['username'] = 'root'
- @configuration['password'] = ''
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ def test_grant_privileges_for_normal_user
+ assert_permissions_granted_for("pat")
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- def test_connection_established_as_normal_user
- assert_permissions_granted_for "pat"
- ActiveRecord::Base.expects(:establish_connection).returns do
- ActiveRecord::Base.expects(:establish_connection).with(
- 'adapter' => 'mysql2',
- 'database' => 'my-app-db',
- 'username' => 'pat',
- 'password' => 'secret'
- )
+ def test_do_not_grant_privileges_for_root_user
+ @configuration['username'] = 'root'
+ @configuration['password'] = ''
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- raise @error
- end
+ def test_connection_established_as_normal_user
+ assert_permissions_granted_for("pat")
+ ActiveRecord::Base.expects(:establish_connection).returns do
+ ActiveRecord::Base.expects(:establish_connection).with(
+ 'adapter' => 'mysql2',
+ 'database' => 'my-app-db',
+ 'username' => 'pat',
+ 'password' => 'secret'
+ )
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ raise @error
end
- def test_sends_output_to_stderr_when_other_errors
- @error.stubs(:errno).returns(42)
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
- $stderr.expects(:puts).at_least_once.returns(nil)
+ def test_sends_output_to_stderr_when_other_errors
+ @error.stubs(:errno).returns(42)
- ActiveRecord::Tasks::DatabaseTasks.create @configuration
- end
+ $stderr.expects(:puts).at_least_once.returns(nil)
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration
+ end
+
+ private
- private
- def assert_permissions_granted_for(db_user)
- db_name = @configuration['database']
- db_password = @configuration['password']
- @connection.expects(:execute).with("GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@'localhost' IDENTIFIED BY '#{db_password}' WITH GRANT OPTION;")
- end
+ def assert_permissions_granted_for(db_user)
+ db_name = @configuration['database']
+ db_password = @configuration['password']
+ @connection.expects(:execute).with("GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@'localhost' IDENTIFIED BY '#{db_password}' WITH GRANT OPTION;")
end
end
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index 970f6bcf4a..937b84bccc 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -98,8 +98,11 @@ class TimestampTest < ActiveRecord::TestCase
task = Task.first
previous_value = task.ending
task.touch(:ending)
+
+ now = Time.now.change(usec: 0)
+
assert_not_equal previous_value, task.ending
- assert_in_delta Time.now, task.ending, 1
+ assert_in_delta now, task.ending, 1
end
def test_touching_an_attribute_updates_timestamp_with_given_time
@@ -120,10 +123,12 @@ class TimestampTest < ActiveRecord::TestCase
previous_ending = task.ending
task.touch(:starting, :ending)
+ now = Time.now.change(usec: 0)
+
assert_not_equal previous_starting, task.starting
assert_not_equal previous_ending, task.ending
- assert_in_delta Time.now, task.starting, 1
- assert_in_delta Time.now, task.ending, 1
+ assert_in_delta now, task.starting, 1
+ assert_in_delta now, task.ending, 1
end
def test_touching_a_record_without_timestamps_is_unexceptional
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index 637f89196e..8a7f19293d 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -34,6 +34,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id"
+ before_commit { |record| record.do_before_commit(nil) }
after_commit { |record| record.do_after_commit(nil) }
after_create_commit { |record| record.do_after_commit(:create) }
after_update_commit { |record| record.do_after_commit(:update) }
@@ -47,6 +48,12 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
@history ||= []
end
+ def before_commit_block(on = nil, &block)
+ @before_commit ||= {}
+ @before_commit[on] ||= []
+ @before_commit[on] << block
+ end
+
def after_commit_block(on = nil, &block)
@after_commit ||= {}
@after_commit[on] ||= []
@@ -59,6 +66,11 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
@after_rollback[on] << block
end
+ def do_before_commit(on)
+ blocks = @before_commit[on] if defined?(@before_commit)
+ blocks.each{|b| b.call(self)} if blocks
+ end
+
def do_after_commit(on)
blocks = @after_commit[on] if defined?(@after_commit)
blocks.each{|b| b.call(self)} if blocks
@@ -74,6 +86,20 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
@first = TopicWithCallbacks.find(1)
end
+ # FIXME: Test behavior, not implementation.
+ def test_before_commit_exception_should_pop_transaction_stack
+ @first.before_commit_block { raise 'better pop this txn from the stack!' }
+
+ original_txn = @first.class.connection.current_transaction
+
+ begin
+ @first.save!
+ fail
+ rescue
+ assert_equal original_txn, @first.class.connection.current_transaction
+ end
+ end
+
def test_call_after_commit_after_transaction_commits
@first.after_commit_block{|r| r.history << :after_commit}
@first.after_rollback_block{|r| r.history << :after_rollback}
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index ec5bdfd725..791b895d02 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -58,6 +58,11 @@ class TransactionTest < ActiveRecord::TestCase
end
end
+ def test_add_to_null_transaction
+ topic = Topic.new
+ topic.add_to_transaction
+ end
+
def test_successful_with_return
committed = false
diff --git a/activerecord/test/cases/validations/absence_validation_test.rb b/activerecord/test/cases/validations/absence_validation_test.rb
index dd43ee358c..c0b3750bcc 100644
--- a/activerecord/test/cases/validations/absence_validation_test.rb
+++ b/activerecord/test/cases/validations/absence_validation_test.rb
@@ -57,19 +57,17 @@ class AbsenceValidationTest < ActiveRecord::TestCase
assert_nothing_raised { boy_klass.new(face: face_with_to_a).valid? }
end
- def test_does_not_validate_if_parent_record_is_validate_false
+ def test_validates_absence_of_virtual_attribute_on_model
repair_validations(Interest) do
- Interest.validates_absence_of(:topic)
- interest = Interest.new(topic: Topic.new(title: "Math"))
- interest.save!(validate: false)
- assert interest.persisted?
+ Interest.send(:attr_accessor, :token)
+ Interest.validates_absence_of(:token)
- man = Man.new(interest_ids: [interest.id])
- man.save!
-
- assert_equal man.interests.size, 1
+ interest = Interest.create!(topic: 'Thought Leadering')
assert interest.valid?
- assert man.valid?
+
+ interest.token = 'tl'
+
+ assert interest.invalid?
end
end
end
diff --git a/activerecord/test/cases/validations/length_validation_test.rb b/activerecord/test/cases/validations/length_validation_test.rb
index c5d8f8895c..78263fd955 100644
--- a/activerecord/test/cases/validations/length_validation_test.rb
+++ b/activerecord/test/cases/validations/length_validation_test.rb
@@ -61,17 +61,19 @@ class LengthValidationTest < ActiveRecord::TestCase
assert_equal pet_count, Pet.count
end
- def test_does_not_validate_length_of_if_parent_record_is_validate_false
- @owner.validates_length_of :name, minimum: 1
- owner = @owner.new
- owner.save!(validate: false)
- assert owner.persisted?
+ def test_validates_length_of_virtual_attribute_on_model
+ repair_validations(Pet) do
+ Pet.send(:attr_accessor, :nickname)
+ Pet.validates_length_of(:name, minimum: 1)
+ Pet.validates_length_of(:nickname, minimum: 1)
- pet = Pet.new(owner_id: owner.id)
- pet.save!
+ pet = Pet.create!(name: 'Fancy Pants', nickname: 'Fancy')
- assert_equal owner.pets.size, 1
- assert owner.valid?
- assert pet.valid?
+ assert pet.valid?
+
+ pet.nickname = ''
+
+ assert pet.invalid?
+ end
end
end
diff --git a/activerecord/test/cases/validations/presence_validation_test.rb b/activerecord/test/cases/validations/presence_validation_test.rb
index 6f8ad06ab6..868d111b8c 100644
--- a/activerecord/test/cases/validations/presence_validation_test.rb
+++ b/activerecord/test/cases/validations/presence_validation_test.rb
@@ -65,19 +65,39 @@ class PresenceValidationTest < ActiveRecord::TestCase
assert_nothing_raised { s.valid? }
end
- def test_does_not_validate_presence_of_if_parent_record_is_validate_false
+ def test_validates_presence_of_virtual_attribute_on_model
repair_validations(Interest) do
+ Interest.send(:attr_accessor, :abbreviation)
Interest.validates_presence_of(:topic)
+ Interest.validates_presence_of(:abbreviation)
+
+ interest = Interest.create!(topic: 'Thought Leadering', abbreviation: 'tl')
+ assert interest.valid?
+
+ interest.abbreviation = ''
+
+ assert interest.invalid?
+ end
+ end
+
+ def test_validations_run_on_persisted_record
+ repair_validations(Interest) do
interest = Interest.new
- interest.save!(validate: false)
- assert interest.persisted?
+ interest.save!
+ assert_predicate interest, :valid?
- man = Man.new(interest_ids: [interest.id])
- man.save!
+ Interest.validates_presence_of(:topic)
- assert_equal man.interests.size, 1
- assert interest.valid?
- assert man.valid?
+ assert_not_predicate interest, :valid?
+ end
+ end
+
+ def test_validates_presence_with_on_context
+ repair_validations(Interest) do
+ Interest.validates_presence_of(:topic, on: :required_name)
+ interest = Interest.new
+ interest.save!
+ assert_not interest.valid?(:required_name)
end
end
end
diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb
index 7502a55391..4c14d93c66 100644
--- a/activerecord/test/cases/validations/uniqueness_validation_test.rb
+++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -5,6 +5,7 @@ require 'models/warehouse_thing'
require 'models/guid'
require 'models/event'
require 'models/dashboard'
+require 'models/uuid_item'
class Wizard < ActiveRecord::Base
self.abstract_class = true
@@ -48,6 +49,18 @@ class BigIntReverseTest < ActiveRecord::Base
validates :engines_count, uniqueness: true
end
+class CoolTopic < Topic
+ validates_uniqueness_of :id
+end
+
+class TopicWithAfterCreate < Topic
+ after_create :set_author
+
+ def set_author
+ update_attributes!(:author_name => "#{title} #{id}")
+ end
+end
+
class UniquenessValidationTest < ActiveRecord::TestCase
INT_MAX_VALUE = 2147483647
@@ -412,23 +425,6 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert topic.valid?
end
- def test_does_not_validate_uniqueness_of_if_parent_record_is_validate_false
- Reply.validates_uniqueness_of(:content)
-
- Reply.create!(content: "Topic Title")
-
- reply = Reply.new(content: "Topic Title")
- reply.save!(validate: false)
- assert reply.persisted?
-
- topic = Topic.new(reply_ids: [reply.id])
- topic.save!
-
- assert_equal topic.replies.size, 1
- assert reply.valid?
- assert topic.valid?
- end
-
def test_validate_uniqueness_of_custom_primary_key
klass = Class.new(ActiveRecord::Base) do
self.table_name = "keyboards"
@@ -469,4 +465,46 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert_match(/\AUnknown primary key for table dashboards in model/, e.message)
assert_match(/Can not validate uniqueness for persisted record without primary key.\z/, e.message)
end
+
+ def test_validate_uniqueness_ignores_itself_when_primary_key_changed
+ Topic.validates_uniqueness_of(:title)
+
+ t = Topic.new("title" => "This is a unique title")
+ assert t.save, "Should save t as unique"
+
+ t.id += 1
+ assert t.valid?, "Should be valid"
+ assert t.save, "Should still save t as unique"
+ end
+
+ def test_validate_uniqueness_with_after_create_performing_save
+ TopicWithAfterCreate.validates_uniqueness_of(:title)
+ topic = TopicWithAfterCreate.create!(:title => "Title1")
+ assert topic.author_name.start_with?("Title1")
+
+ topic2 = TopicWithAfterCreate.new(:title => "Title1")
+ refute topic2.valid?
+ assert_equal(["has already been taken"], topic2.errors[:title])
+ end
+
+ def test_validate_uniqueness_uuid
+ skip unless current_adapter?(:PostgreSQLAdapter)
+ item = UuidItem.create!(uuid: SecureRandom.uuid, title: 'item1')
+ item.update(title: 'item1-title2')
+ assert_empty item.errors
+
+ item2 = UuidValidatingItem.create!(uuid: SecureRandom.uuid, title: 'item2')
+ item2.update(title: 'item2-title2')
+ assert_empty item2.errors
+ end
+
+ def test_validate_uniqueness_regular_id
+ item = CoolTopic.create!(title: 'MyItem')
+ assert_empty item.errors
+
+ item2 = CoolTopic.new(id: item.id, title: 'MyItem2')
+ refute item2.valid?
+
+ assert_equal(["has already been taken"], item2.errors[:id])
+ end
end
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index d04f4f7ce7..85e33d2218 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -130,7 +130,7 @@ class ValidationsTest < ActiveRecord::TestCase
def test_validates_acceptance_of_with_non_existent_table
Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base)
- assert_nothing_raised ActiveRecord::StatementInvalid do
+ assert_nothing_raised do
IncorporealModel.validates_acceptance_of(:incorporeal_column)
end
end
diff --git a/activerecord/test/fixtures/author_addresses.yml b/activerecord/test/fixtures/author_addresses.yml
index 7b90572187..cf75e5998d 100644
--- a/activerecord/test/fixtures/author_addresses.yml
+++ b/activerecord/test/fixtures/author_addresses.yml
@@ -3,3 +3,9 @@ david_address:
david_address_extra:
id: 2
+
+mary_address:
+ id: 3
+
+bob_address:
+ id: 4
diff --git a/activerecord/test/fixtures/authors.yml b/activerecord/test/fixtures/authors.yml
index 832236a486..41c124179e 100644
--- a/activerecord/test/fixtures/authors.yml
+++ b/activerecord/test/fixtures/authors.yml
@@ -9,7 +9,9 @@ david:
mary:
id: 2
name: Mary
+ author_address_id: 3
bob:
id: 3
name: Bob
+ author_address_id: 4
diff --git a/activerecord/test/fixtures/naked/yml/trees.yml b/activerecord/test/fixtures/naked/yml/trees.yml
new file mode 100644
index 0000000000..d163b98f21
--- /dev/null
+++ b/activerecord/test/fixtures/naked/yml/trees.yml
@@ -0,0 +1,3 @@
+root:
+ :id: 1
+ :name: The Root
diff --git a/activerecord/test/fixtures/price_estimates.yml b/activerecord/test/fixtures/price_estimates.yml
index 1149ab17a2..406d65a142 100644
--- a/activerecord/test/fixtures/price_estimates.yml
+++ b/activerecord/test/fixtures/price_estimates.yml
@@ -1,7 +1,16 @@
-saphire_1:
+sapphire_1:
price: 10
estimate_of: sapphire (Treasure)
sapphire_2:
price: 20
estimate_of: sapphire (Treasure)
+
+diamond:
+ price: 30
+ estimate_of: diamond (Treasure)
+
+honda:
+ price: 40
+ estimate_of_type: Car
+ estimate_of_id: 1
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 0d90cbb110..f25e31b13d 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -75,7 +75,7 @@ class Author < ActiveRecord::Base
has_many :posts_with_multiple_callbacks, :class_name => "Post",
:before_add => [:log_before_adding, Proc.new {|o, r| o.post_log << "before_adding_proc#{r.id || '<new>'}"}],
:after_add => [:log_after_adding, Proc.new {|o, r| o.post_log << "after_adding_proc#{r.id || '<new>'}"}]
- has_many :unchangable_posts, :class_name => "Post", :before_add => :raise_exception, :after_add => :log_after_adding
+ has_many :unchangeable_posts, :class_name => "Post", :before_add => :raise_exception, :after_add => :log_after_adding
has_many :categorizations
has_many :categories, :through => :categorizations
diff --git a/activerecord/test/models/book.rb b/activerecord/test/models/book.rb
index 1927191393..e43e5c3901 100644
--- a/activerecord/test/models/book.rb
+++ b/activerecord/test/models/book.rb
@@ -14,6 +14,7 @@ class Book < ActiveRecord::Base
enum author_visibility: [:visible, :invisible], _prefix: true
enum illustrator_visibility: [:visible, :invisible], _prefix: true
enum font_size: [:small, :medium, :large], _prefix: :with, _suffix: true
+ enum cover: { hard: 'hard', soft: 'soft' }
def published!
super
diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb
index 778c22b1f6..0f37e9a289 100644
--- a/activerecord/test/models/car.rb
+++ b/activerecord/test/models/car.rb
@@ -12,6 +12,8 @@ class Car < ActiveRecord::Base
has_many :engines, :dependent => :destroy, inverse_of: :my_car
has_many :wheels, :as => :wheelable, :dependent => :destroy
+ has_many :price_estimates, :as => :estimate_of
+
scope :incl_tyres, -> { includes(:tyres) }
scope :incl_engines, -> { includes(:engines) }
diff --git a/activerecord/test/models/chef.rb b/activerecord/test/models/chef.rb
index 698a52e045..9d3dd01016 100644
--- a/activerecord/test/models/chef.rb
+++ b/activerecord/test/models/chef.rb
@@ -2,3 +2,7 @@ class Chef < ActiveRecord::Base
belongs_to :employable, polymorphic: true
has_many :recipes
end
+
+class ChefList < Chef
+ belongs_to :employable_list, polymorphic: true
+end
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index b38b17e90e..dcc5c5a310 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -14,6 +14,7 @@ class Comment < ActiveRecord::Base
has_many :ratings
belongs_to :first_post, :foreign_key => :post_id
+ belongs_to :special_post_with_default_scope, foreign_key: :post_id
has_many :children, :class_name => 'Comment', :foreign_key => :parent_id
belongs_to :parent, :class_name => 'Comment', :counter_cache => :children_count
diff --git a/activerecord/test/models/hotel.rb b/activerecord/test/models/hotel.rb
index 491f8dfde3..9c90ffcff4 100644
--- a/activerecord/test/models/hotel.rb
+++ b/activerecord/test/models/hotel.rb
@@ -3,5 +3,9 @@ class Hotel < ActiveRecord::Base
has_many :chefs, through: :departments
has_many :cake_designers, source_type: 'CakeDesigner', source: :employable, through: :chefs
has_many :drink_designers, source_type: 'DrinkDesigner', source: :employable, through: :chefs
+
+ has_many :chef_lists, as: :employable_list
+ has_many :mocktail_designers, through: :chef_lists, source: :employable, :source_type => "MocktailDesigner"
+
has_many :recipes, through: :chefs
end
diff --git a/activerecord/test/models/mocktail_designer.rb b/activerecord/test/models/mocktail_designer.rb
new file mode 100644
index 0000000000..77b44651a3
--- /dev/null
+++ b/activerecord/test/models/mocktail_designer.rb
@@ -0,0 +1,2 @@
+class MocktailDesigner < DrinkDesigner
+end
diff --git a/activerecord/test/models/notification.rb b/activerecord/test/models/notification.rb
index b4b4b8f1b6..82edc64b68 100644
--- a/activerecord/test/models/notification.rb
+++ b/activerecord/test/models/notification.rb
@@ -1,2 +1,3 @@
class Notification < ActiveRecord::Base
+ validates_presence_of :message
end
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index 23cebe2602..bf3079a1df 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -263,3 +263,10 @@ end
class SerializedPost < ActiveRecord::Base
serialize :title
end
+
+class ConditionalStiPost < Post
+ default_scope { where(title: 'Untitled') }
+end
+
+class SubConditionalStiPost < ConditionalStiPost
+end
diff --git a/activerecord/test/models/uuid_item.rb b/activerecord/test/models/uuid_item.rb
new file mode 100644
index 0000000000..2353e40213
--- /dev/null
+++ b/activerecord/test/models/uuid_item.rb
@@ -0,0 +1,6 @@
+class UuidItem < ActiveRecord::Base
+end
+
+class UuidValidatingItem < UuidItem
+ validates_uniqueness_of :uuid
+end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index 92e0b197a7..101e657982 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -1,29 +1,35 @@
ActiveRecord::Schema.define do
+
+ if ActiveRecord::Base.connection.version >= '5.6.0'
+ create_table :datetime_defaults, force: true do |t|
+ t.datetime :modified_datetime, default: -> { 'CURRENT_TIMESTAMP' }
+ end
+ end
+
create_table :binary_fields, force: true do |t|
t.binary :var_binary, limit: 255
t.binary :var_binary_large, limit: 4095
- t.blob :tiny_blob, limit: 255
- t.binary :normal_blob, limit: 65535
- t.binary :medium_blob, limit: 16777215
- t.binary :long_blob, limit: 2147483647
- t.text :tiny_text, limit: 255
- t.text :normal_text, limit: 65535
- t.text :medium_text, limit: 16777215
- t.text :long_text, limit: 2147483647
- end
+ t.tinyblob :tiny_blob
+ t.blob :normal_blob
+ t.mediumblob :medium_blob
+ t.longblob :long_blob
+ t.tinytext :tiny_text
+ t.text :normal_text
+ t.mediumtext :medium_text
+ t.longtext :long_text
- add_index :binary_fields, :var_binary
+ t.index :var_binary
+ end
- create_table :key_tests, force: true, :options => 'ENGINE=MyISAM' do |t|
+ create_table :key_tests, force: true, options: 'ENGINE=MyISAM' do |t|
t.string :awesome
t.string :pizza
t.string :snacks
+ t.index :awesome, type: :fulltext, name: 'index_key_tests_on_awesome'
+ t.index :pizza, using: :btree, name: 'index_key_tests_on_pizza'
+ t.index :snacks, name: 'index_key_tests_on_snack'
end
- add_index :key_tests, :awesome, :type => :fulltext, :name => 'index_key_tests_on_awesome'
- add_index :key_tests, :pizza, :using => :btree, :name => 'index_key_tests_on_pizza'
- add_index :key_tests, :snacks, :name => 'index_key_tests_on_snack'
-
create_table :collation_tests, id: false, force: true do |t|
t.string :string_cs_column, limit: 1, collation: 'utf8_bin'
t.string :string_ci_column, limit: 1, collation: 'utf8_general_ci'
@@ -55,7 +61,7 @@ SQL
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE enum_tests (
- enum_column ENUM('text','blob','tiny','medium','long')
+ enum_column ENUM('text','blob','tiny','medium','long','unsigned','bigint')
)
SQL
end
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
deleted file mode 100644
index 553cb56103..0000000000
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-ActiveRecord::Schema.define do
- create_table :binary_fields, force: true do |t|
- t.binary :var_binary, limit: 255
- t.binary :var_binary_large, limit: 4095
- t.blob :tiny_blob, limit: 255
- t.binary :normal_blob, limit: 65535
- t.binary :medium_blob, limit: 16777215
- t.binary :long_blob, limit: 2147483647
- t.text :tiny_text, limit: 255
- t.text :normal_text, limit: 65535
- t.text :medium_text, limit: 16777215
- t.text :long_text, limit: 2147483647
- end
-
- add_index :binary_fields, :var_binary
-
- create_table :key_tests, force: true, :options => 'ENGINE=MyISAM' do |t|
- t.string :awesome
- t.string :pizza
- t.string :snacks
- end
-
- add_index :key_tests, :awesome, :type => :fulltext, :name => 'index_key_tests_on_awesome'
- add_index :key_tests, :pizza, :using => :btree, :name => 'index_key_tests_on_pizza'
- add_index :key_tests, :snacks, :name => 'index_key_tests_on_snack'
-
- create_table :collation_tests, id: false, force: true do |t|
- t.string :string_cs_column, limit: 1, collation: 'utf8_bin'
- t.string :string_ci_column, limit: 1, collation: 'utf8_general_ci'
- end
-
- ActiveRecord::Base.connection.execute <<-SQL
-DROP PROCEDURE IF EXISTS ten;
-SQL
-
- ActiveRecord::Base.connection.execute <<-SQL
-CREATE PROCEDURE ten() SQL SECURITY INVOKER
-BEGIN
- select 10;
-END
-SQL
-
- ActiveRecord::Base.connection.execute <<-SQL
-DROP PROCEDURE IF EXISTS topics;
-SQL
-
- ActiveRecord::Base.connection.execute <<-SQL
-CREATE PROCEDURE topics(IN num INT) SQL SECURITY INVOKER
-BEGIN
- select * from topics limit num;
-END
-SQL
-
- ActiveRecord::Base.connection.drop_table "enum_tests", if_exists: true
-
- ActiveRecord::Base.connection.execute <<-SQL
-CREATE TABLE enum_tests (
- enum_column ENUM('text','blob','tiny','medium','long')
-)
-SQL
-
-end
diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb
index df0362573b..24713f722a 100644
--- a/activerecord/test/schema/postgresql_specific_schema.rb
+++ b/activerecord/test/schema/postgresql_specific_schema.rb
@@ -11,7 +11,23 @@ ActiveRecord::Schema.define do
t.uuid :uuid_parent_id
end
- %w(postgresql_times postgresql_oids defaults postgresql_timestamp_with_zones
+ create_table :defaults, force: true do |t|
+ t.date :modified_date, default: -> { 'CURRENT_DATE' }
+ t.date :modified_date_function, default: -> { 'now()' }
+ t.date :fixed_date, default: '2004-01-01'
+ t.datetime :modified_time, default: -> { 'CURRENT_TIMESTAMP' }
+ t.datetime :modified_time_function, default: -> { 'now()' }
+ t.datetime :fixed_time, default: '2004-01-01 00:00:00.000000-00'
+ t.column :char1, 'char(1)', default: 'Y'
+ t.string :char2, limit: 50, default: 'a varchar field'
+ t.text :char3, default: 'a text field'
+ t.bigint :bigint_default, default: -> { '0::bigint' }
+ t.text :multiline_default, default: '--- []
+
+'
+ end
+
+ %w(postgresql_times postgresql_oids postgresql_timestamp_with_zones
postgresql_partitioned_table postgresql_partitioned_table_parent).each do |table_name|
drop_table table_name, if_exists: true
end
@@ -28,25 +44,6 @@ ActiveRecord::Schema.define do
end
execute <<_SQL
- CREATE TABLE defaults (
- id serial primary key,
- modified_date date default CURRENT_DATE,
- modified_date_function date default now(),
- fixed_date date default '2004-01-01',
- modified_time timestamp default CURRENT_TIMESTAMP,
- modified_time_function timestamp default now(),
- fixed_time timestamp default '2004-01-01 00:00:00.000000-00',
- char1 char(1) default 'Y',
- char2 character varying(50) default 'a varchar field',
- char3 text default 'a text field',
- bigint_default bigint default 0::bigint,
- multiline_default text DEFAULT '--- []
-
-'::text
-);
-_SQL
-
- execute <<_SQL
CREATE TABLE postgresql_times (
id SERIAL PRIMARY KEY,
time_interval INTERVAL,
@@ -109,4 +106,9 @@ _SQL
t.integer :big_int_data_points, limit: 8, array: true
t.decimal :decimal_array_default, array: true, default: [1.23, 3.45]
end
+
+ create_table :uuid_items, force: true, id: false do |t|
+ t.uuid :uuid, primary_key: true
+ t.string :title
+ end
end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 025184f63a..2a8996f35c 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -104,6 +104,7 @@ ActiveRecord::Schema.define do
t.column :author_visibility, :integer, default: 0
t.column :illustrator_visibility, :integer, default: 0
t.column :font_size, :integer, default: 0
+ t.column :cover, :string, default: 'hard'
end
create_table :booleans, force: true do |t|
@@ -201,12 +202,11 @@ ActiveRecord::Schema.define do
t.integer :rating, default: 1
t.integer :account_id
t.string :description, default: ""
+ t.index [:firm_id, :type, :rating], name: "company_index"
+ t.index [:firm_id, :type], name: "company_partial_index", where: "rating > 10"
+ t.index :name, name: 'company_name_index', using: :btree
end
- add_index :companies, [:firm_id, :type, :rating], name: "company_index"
- add_index :companies, [:firm_id, :type], name: "company_partial_index", where: "rating > 10"
- add_index :companies, :name, name: 'company_name_index', using: :btree
-
create_table :content, force: true do |t|
t.string :title
end
@@ -303,8 +303,8 @@ ActiveRecord::Schema.define do
create_table :edges, force: true, id: false do |t|
t.column :source_id, :integer, null: false
t.column :sink_id, :integer, null: false
+ t.index [:source_id, :sink_id], unique: true, name: 'unique_edge_index'
end
- add_index :edges, [:source_id, :sink_id], unique: true, name: 'unique_edge_index'
create_table :engines, force: true do |t|
t.integer :car_id
@@ -781,8 +781,8 @@ ActiveRecord::Schema.define do
t.string :nick, null: false
t.string :name
t.column :books_count, :integer, null: false, default: 0
+ t.index :nick, unique: true
end
- add_index :subscribers, :nick, unique: true
create_table :subscriptions, force: true do |t|
t.string :subscriber_id
@@ -929,7 +929,7 @@ ActiveRecord::Schema.define do
t.string :treaty_id
t.string :name
end
- create_table :countries_treaties, force: true, id: false do |t|
+ create_table :countries_treaties, force: true, primary_key: [:country_id, :treaty_id] do |t|
t.string :country_id, null: false
t.string :treaty_id, null: false
end
@@ -975,6 +975,8 @@ ActiveRecord::Schema.define do
t.integer :employable_id
t.string :employable_type
t.integer :department_id
+ t.string :employable_list_type
+ t.integer :employable_list_id
end
create_table :recipes, force: true do |t|
t.integer :chef_id