diff options
Diffstat (limited to 'activerecord/test')
51 files changed, 695 insertions, 388 deletions
diff --git a/activerecord/test/cases/adapters/mysql/datetime_test.rb b/activerecord/test/cases/adapters/mysql/datetime_test.rb deleted file mode 100644 index ae00f4e131..0000000000 --- a/activerecord/test/cases/adapters/mysql/datetime_test.rb +++ /dev/null @@ -1,87 +0,0 @@ -require 'cases/helper' - -if mysql_56? - class DateTimeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - class Foo < ActiveRecord::Base; end - - def test_default_datetime_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime - assert_nil activerecord_column_option('foos', 'created_at', 'precision') - end - - def test_datetime_data_type_with_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, precision: 1 - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, precision: 5 - assert_equal 1, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_timestamps_helper_with_custom_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_passing_precision_to_datetime_does_not_set_limit - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_nil activerecord_column_option('foos', 'created_at', 'limit') - assert_nil activerecord_column_option('foos', 'updated_at', 'limit') - end - - def test_invalid_datetime_precision_raises_error - assert_raises ActiveRecord::ActiveRecordError do - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 7 - end - end - end - - def test_mysql_agrees_with_activerecord_about_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_equal 4, mysql_datetime_precision('foos', 'created_at') - assert_equal 4, mysql_datetime_precision('foos', 'updated_at') - end - - def test_formatting_datetime_according_to_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.datetime :created_at, precision: 0 - t.datetime :updated_at, precision: 4 - end - date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999) - Foo.create!(created_at: date, updated_at: date) - assert foo = Foo.find_by(created_at: date) - assert_equal date.to_s, foo.created_at.to_s - assert_equal date.to_s, foo.updated_at.to_s - assert_equal 000000, foo.created_at.usec - assert_equal 999900, foo.updated_at.usec - end - - private - - def mysql_datetime_precision(table_name, column_name) - results = ActiveRecord::Base.connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name = '#{table_name}'") - result = results.find do |result_hash| - result_hash["column_name"] == column_name - end - result && result["datetime_precision"] - end - - def activerecord_column_option(tablename, column_name, option) - result = ActiveRecord::Base.connection.columns(tablename).find do |column| - column.name == column_name - end - result && result.send(option) - end - end -end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index d261e2db55..ff8ce93248 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -122,11 +122,4 @@ class MysqlConnectionTest < ActiveRecord::TestCase ensure @connection.execute "DROP TABLE `bar_baz`" end - - if mysql_56? - def test_quote_time_usec - assert_equal "'1970-01-01 00:00:00.000000'", @connection.quote(Time.at(0)) - assert_equal "'1970-01-01 00:00:00.000000'", @connection.quote(Time.at(0).to_datetime) - end - end end diff --git a/activerecord/test/cases/adapters/mysql2/datetime_test.rb b/activerecord/test/cases/adapters/mysql2/datetime_test.rb deleted file mode 100644 index ae00f4e131..0000000000 --- a/activerecord/test/cases/adapters/mysql2/datetime_test.rb +++ /dev/null @@ -1,87 +0,0 @@ -require 'cases/helper' - -if mysql_56? - class DateTimeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - - class Foo < ActiveRecord::Base; end - - def test_default_datetime_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime - assert_nil activerecord_column_option('foos', 'created_at', 'precision') - end - - def test_datetime_data_type_with_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, precision: 1 - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, precision: 5 - assert_equal 1, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_timestamps_helper_with_custom_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_passing_precision_to_datetime_does_not_set_limit - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_nil activerecord_column_option('foos', 'created_at', 'limit') - assert_nil activerecord_column_option('foos', 'updated_at', 'limit') - end - - def test_invalid_datetime_precision_raises_error - assert_raises ActiveRecord::ActiveRecordError do - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 7 - end - end - end - - def test_mysql_agrees_with_activerecord_about_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.timestamps null: true, precision: 4 - end - assert_equal 4, mysql_datetime_precision('foos', 'created_at') - assert_equal 4, mysql_datetime_precision('foos', 'updated_at') - end - - def test_formatting_datetime_according_to_precision - ActiveRecord::Base.connection.create_table(:foos, force: true) do |t| - t.datetime :created_at, precision: 0 - t.datetime :updated_at, precision: 4 - end - date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999) - Foo.create!(created_at: date, updated_at: date) - assert foo = Foo.find_by(created_at: date) - assert_equal date.to_s, foo.created_at.to_s - assert_equal date.to_s, foo.updated_at.to_s - assert_equal 000000, foo.created_at.usec - assert_equal 999900, foo.updated_at.usec - end - - private - - def mysql_datetime_precision(table_name, column_name) - results = ActiveRecord::Base.connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name = '#{table_name}'") - result = results.find do |result_hash| - result_hash["column_name"] == column_name - end - result && result["datetime_precision"] - end - - def activerecord_column_option(tablename, column_name, option) - result = ActiveRecord::Base.connection.columns(tablename).find do |column| - column.name == column_name - end - result && result.send(option) - end - 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 06b0cb5515..271b570eb5 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -18,21 +18,29 @@ module ActiveRecord smtn = ActiveRecord::Migrator.schema_migrations_table_name connection.drop_table smtn, if_exists: true - config = connection.instance_variable_get(:@config) - original_encoding = config[:encoding] + database_name = connection.current_database + database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'") + + original_charset = database_info["DEFAULT_CHARACTER_SET_NAME"] + original_collation = database_info["DEFAULT_COLLATION_NAME"] + + execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET utf8mb4") - config[:encoding] = 'utf8mb4' connection.initialize_schema_migrations_table assert connection.column_exists?(smtn, :version, :string, limit: Mysql2Adapter::MAX_INDEX_LENGTH_FOR_UTF8MB4) ensure - config[:encoding] = original_encoding + execute("ALTER DATABASE #{database_name} DEFAULT CHARACTER SET #{original_charset} COLLATE #{original_collation}") end private def connection @connection ||= ActiveRecord::Base.connection end + + def execute(sql) + connection.execute(sql) + end end end end diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index 35b792b1c2..3d5b7e5137 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -36,14 +36,11 @@ class PostgresqlArrayTest < ActiveRecord::TestCase assert_equal :string, @column.type assert_equal "character varying", @column.sql_type assert @column.array? - assert_not @type.number? assert_not @type.binary? ratings_column = PgArray.columns_hash['ratings'] assert_equal :integer, ratings_column.type - type = PgArray.type_for_attribute("ratings") assert ratings_column.array? - assert_not type.number? end def test_default diff --git a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb index d6b976a6d0..6c6b4dc22a 100644 --- a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb +++ b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb @@ -13,6 +13,8 @@ class PostgresqlBitStringTest < ActiveRecord::TestCase @connection.create_table('postgresql_bit_strings', :force => true) do |t| t.bit :a_bit, default: "00000011", limit: 8 t.bit_varying :a_bit_varying, default: "0011", limit: 4 + t.bit :another_bit + t.bit_varying :another_bit_varying end end @@ -28,7 +30,6 @@ class PostgresqlBitStringTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlBitString.type_for_attribute("a_bit") - assert_not type.number? assert_not type.binary? end @@ -39,7 +40,6 @@ class PostgresqlBitStringTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlBitString.type_for_attribute("a_bit_varying") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/citext_test.rb b/activerecord/test/cases/adapters/postgresql/citext_test.rb index 077f0271e2..0ee2a21484 100644 --- a/activerecord/test/cases/adapters/postgresql/citext_test.rb +++ b/activerecord/test/cases/adapters/postgresql/citext_test.rb @@ -34,7 +34,6 @@ if ActiveRecord::Base.connection.supports_extensions? assert_not column.array? type = Citext.type_for_attribute('cival') - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb index 0c0d2465b2..83dfb18e95 100644 --- a/activerecord/test/cases/adapters/postgresql/composite_test.rb +++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb @@ -52,7 +52,6 @@ class PostgresqlCompositeTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlComposite.type_for_attribute("address") - assert_not type.number? assert_not type.binary? end @@ -115,7 +114,6 @@ class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlComposite.type_for_attribute("address") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/domain_test.rb b/activerecord/test/cases/adapters/postgresql/domain_test.rb index 702de07597..b7d776b40c 100644 --- a/activerecord/test/cases/adapters/postgresql/domain_test.rb +++ b/activerecord/test/cases/adapters/postgresql/domain_test.rb @@ -31,7 +31,6 @@ class PostgresqlDomainTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlDomain.type_for_attribute("price") - assert type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/enum_test.rb b/activerecord/test/cases/adapters/postgresql/enum_test.rb index 7739d2ee3b..acb09b0607 100644 --- a/activerecord/test/cases/adapters/postgresql/enum_test.rb +++ b/activerecord/test/cases/adapters/postgresql/enum_test.rb @@ -33,7 +33,6 @@ class PostgresqlEnumTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlEnum.type_for_attribute("current_mood") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/full_text_test.rb b/activerecord/test/cases/adapters/postgresql/full_text_test.rb index 8357dcb3dc..81891a90fa 100644 --- a/activerecord/test/cases/adapters/postgresql/full_text_test.rb +++ b/activerecord/test/cases/adapters/postgresql/full_text_test.rb @@ -23,7 +23,6 @@ class PostgresqlFullTextTest < ActiveRecord::TestCase assert_not column.array? type = Tsvector.type_for_attribute("text_vector") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 5d2e86c5a0..4b25381a83 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -28,7 +28,6 @@ class PostgresqlPointTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlPoint.type_for_attribute("x") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 121f347986..11053a6e38 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -56,7 +56,6 @@ if ActiveRecord::Base.connection.supports_extensions? assert_equal "hstore", @column.sql_type assert_not @column.array? - assert_not @type.number? assert_not @type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb index dd7b67bad7..3b123f979e 100644 --- a/activerecord/test/cases/adapters/postgresql/json_test.rb +++ b/activerecord/test/cases/adapters/postgresql/json_test.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require "cases/helper" require 'support/schema_dumping_helper' @@ -13,20 +14,18 @@ module PostgresqlJSONSharedTestCases def setup @connection = ActiveRecord::Base.connection begin - @connection.transaction do - @connection.create_table('json_data_type') do |t| - t.public_send column_type, 'payload', default: {} # t.json 'payload', default: {} - t.public_send column_type, 'settings' # t.json 'settings' - end + @connection.create_table('json_data_type') do |t| + t.public_send column_type, 'payload', default: {} # t.json 'payload', default: {} + t.public_send column_type, 'settings' # t.json 'settings' end rescue ActiveRecord::StatementInvalid - skip "do not test on PG without json" + skip "do not test on PostgreSQL without #{column_type} type." end @column = JsonDataType.columns_hash['payload'] end def teardown - @connection.execute 'drop table if exists json_data_type' + @connection.drop_table :json_data_type, if_exists: true end def test_column @@ -36,7 +35,6 @@ module PostgresqlJSONSharedTestCases assert_not column.array? type = JsonDataType.type_for_attribute("payload") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/ltree_test.rb b/activerecord/test/cases/adapters/postgresql/ltree_test.rb index ca17edfd03..2b3823f9f1 100644 --- a/activerecord/test/cases/adapters/postgresql/ltree_test.rb +++ b/activerecord/test/cases/adapters/postgresql/ltree_test.rb @@ -32,7 +32,6 @@ class PostgresqlLtreeTest < ActiveRecord::TestCase assert_not column.array? type = Ltree.type_for_attribute('path') - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/money_test.rb b/activerecord/test/cases/adapters/postgresql/money_test.rb index 4288f754c0..ba9af4be6f 100644 --- a/activerecord/test/cases/adapters/postgresql/money_test.rb +++ b/activerecord/test/cases/adapters/postgresql/money_test.rb @@ -10,8 +10,8 @@ class PostgresqlMoneyTest < ActiveRecord::TestCase @connection = ActiveRecord::Base.connection @connection.execute("set lc_monetary = 'C'") @connection.create_table('postgresql_moneys', force: true) do |t| - t.column "wealth", "money" - t.column "depth", "money", default: "150.55" + t.money "wealth" + t.money "depth", default: "150.55" end end @@ -27,7 +27,6 @@ class PostgresqlMoneyTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlMoney.type_for_attribute("wealth") - assert type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/network_test.rb b/activerecord/test/cases/adapters/postgresql/network_test.rb index efe754ac7c..4cd2d4d5f3 100644 --- a/activerecord/test/cases/adapters/postgresql/network_test.rb +++ b/activerecord/test/cases/adapters/postgresql/network_test.rb @@ -25,7 +25,6 @@ class PostgresqlNetworkTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlNetworkAddress.type_for_attribute("cidr_address") - assert_not type.number? assert_not type.binary? end @@ -36,7 +35,6 @@ class PostgresqlNetworkTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlNetworkAddress.type_for_attribute("inet_address") - assert_not type.number? assert_not type.binary? end @@ -47,7 +45,6 @@ class PostgresqlNetworkTest < ActiveRecord::TestCase assert_not column.array? type = PostgresqlNetworkAddress.type_for_attribute("mac_address") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/adapters/postgresql/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index 894cf1ffa2..60baacf67a 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -27,11 +27,6 @@ module ActiveRecord assert_equal "'Infinity'", @conn.quote(infinity) end - def test_quote_time_usec - assert_equal "'1970-01-01 00:00:00.000000'", @conn.quote(Time.at(0)) - assert_equal "'1970-01-01 00:00:00.000000'", @conn.quote(Time.at(0).to_datetime) - end - def test_quote_range range = "1,2]'; SELECT * FROM users; --".."a" type = OID::Range.new(Type::Integer.new, :int8range) diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index eb32c4d2c2..da14063e20 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -70,53 +70,6 @@ class TimestampTest < ActiveRecord::TestCase assert_equal(-1.0 / 0.0, d.updated_at) end - def test_default_datetime_precision - ActiveRecord::Base.connection.create_table(:foos) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime - assert_nil activerecord_column_option('foos', 'created_at', 'precision') - end - - def test_timestamp_data_type_with_precision - ActiveRecord::Base.connection.create_table(:foos) - ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, :precision => 0 - ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, :precision => 5 - assert_equal 0, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_timestamps_helper_with_custom_precision - ActiveRecord::Base.connection.create_table(:foos) do |t| - t.timestamps :null => true, :precision => 4 - end - assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') - assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') - end - - def test_passing_precision_to_timestamp_does_not_set_limit - ActiveRecord::Base.connection.create_table(:foos) do |t| - t.timestamps :null => true, :precision => 4 - end - assert_nil activerecord_column_option("foos", "created_at", "limit") - assert_nil activerecord_column_option("foos", "updated_at", "limit") - end - - def test_invalid_timestamp_precision_raises_error - assert_raises ActiveRecord::ActiveRecordError do - ActiveRecord::Base.connection.create_table(:foos) do |t| - t.timestamps :null => true, :precision => 7 - end - end - end - - def test_postgres_agrees_with_activerecord_about_precision - ActiveRecord::Base.connection.create_table(:foos) do |t| - t.timestamps :null => true, :precision => 4 - end - assert_equal '4', pg_datetime_precision('foos', 'created_at') - assert_equal '4', pg_datetime_precision('foos', 'updated_at') - end - def test_bc_timestamp date = Date.new(0) - 1.week Developer.create!(:name => "aaron", :updated_at => date) @@ -134,21 +87,4 @@ class TimestampTest < ActiveRecord::TestCase Developer.create!(:name => "yahagi", :updated_at => date) assert_equal date, Developer.find_by_name("yahagi").updated_at end - - private - - def pg_datetime_precision(table_name, column_name) - results = ActiveRecord::Base.connection.execute("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name ='#{table_name}'") - result = results.find do |result_hash| - result_hash["column_name"] == column_name - end - result && result["datetime_precision"] - end - - def activerecord_column_option(tablename, column_name, option) - result = ActiveRecord::Base.connection.columns(tablename).find do |column| - column.name == column_name - end - result && result.send(option) - end end diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 1d0f013a26..6693843497 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -51,7 +51,6 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase assert_not column.array? type = UUIDType.type_for_attribute("guid") - assert_not type.number? assert_not type.binary? end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 19f4384e83..fde7b0ea3a 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1678,6 +1678,82 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 3, firm.clients.size end + def test_calling_none_should_count_instead_of_loading_association + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.none? # use count query + end + assert !firm.clients.loaded? + end + + def test_calling_none_on_loaded_association_should_not_use_query + firm = companies(:first_firm) + firm.clients.collect # force load + assert_no_queries { assert ! firm.clients.none? } + end + + def test_calling_none_should_defer_to_collection_if_using_a_block + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.expects(:size).never + firm.clients.none? { true } + end + assert firm.clients.loaded? + end + + def test_calling_none_should_return_true_if_none + firm = companies(:another_firm) + assert firm.clients_like_ms.none? + assert_equal 0, firm.clients_like_ms.size + end + + def test_calling_none_should_return_false_if_any + firm = companies(:first_firm) + assert !firm.limited_clients.none? + assert_equal 1, firm.limited_clients.size + end + + def test_calling_one_should_count_instead_of_loading_association + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.one? # use count query + end + assert !firm.clients.loaded? + end + + def test_calling_one_on_loaded_association_should_not_use_query + firm = companies(:first_firm) + firm.clients.collect # force load + assert_no_queries { assert ! firm.clients.one? } + end + + def test_calling_one_should_defer_to_collection_if_using_a_block + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.expects(:size).never + firm.clients.one? { true } + end + assert firm.clients.loaded? + end + + def test_calling_one_should_return_false_if_zero + firm = companies(:another_firm) + assert ! firm.clients_like_ms.one? + assert_equal 0, firm.clients_like_ms.size + end + + def test_calling_one_should_return_true_if_one + firm = companies(:first_firm) + assert firm.limited_clients.one? + assert_equal 1, firm.limited_clients.size + end + + def test_calling_one_should_return_false_if_more_than_one + firm = companies(:first_firm) + assert ! firm.clients.one? + assert_equal 3, firm.clients.size + end + def test_joins_with_namespaced_model_should_use_correct_type old = ActiveRecord::Base.store_full_sti_class ActiveRecord::Base.store_full_sti_class = true diff --git a/activerecord/test/cases/attribute_decorators_test.rb b/activerecord/test/cases/attribute_decorators_test.rb index 9ad02ffae8..0b96319cbd 100644 --- a/activerecord/test/cases/attribute_decorators_test.rb +++ b/activerecord/test/cases/attribute_decorators_test.rb @@ -51,7 +51,7 @@ module ActiveRecord end test "undecorated columns are not touched" do - Model.attribute :another_string, Type::String.new, default: 'something or other' + Model.attribute :another_string, :string, default: 'something or other' Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) } assert_equal 'something or other', Model.new.another_string @@ -86,7 +86,7 @@ module ActiveRecord end test "decorating attributes does not modify parent classes" do - Model.attribute :another_string, Type::String.new, default: 'whatever' + Model.attribute :another_string, :string, default: 'whatever' Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) } child_class = Class.new(Model) child_class.decorate_attribute_type(:another_string, :test) { |t| StringDecorator.new(t) } @@ -110,7 +110,7 @@ module ActiveRecord end test "decorating with a proc" do - Model.attribute :an_int, Type::Integer.new + Model.attribute :an_int, :integer type_is_integer = proc { |_, type| type.type == :integer } Model.decorate_matching_attribute_types type_is_integer, :multiplier do |type| Multiplier.new(type) diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb index 8025c7c4d2..112cd2fb14 100644 --- a/activerecord/test/cases/attribute_set_test.rb +++ b/activerecord/test/cases/attribute_set_test.rb @@ -65,6 +65,16 @@ module ActiveRecord assert_equal({ foo: 1, bar: 2.2 }, attributes.to_h) end + test "to_hash maintains order" do + builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Float.new) + attributes = builder.build_from_database(foo: '2.2', bar: '3.3') + + attributes[:bar] + hash = attributes.to_h + + assert_equal [[:foo, 2], [:bar, 3.3]], hash.to_a + end + test "values_before_type_cast" do builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new) attributes = builder.build_from_database(foo: '1.1', bar: '2.2') diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index 6f331c5985..a753e8b74e 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -1,17 +1,17 @@ require 'cases/helper' class OverloadedType < ActiveRecord::Base - attribute :overloaded_float, Type::Integer.new - attribute :overloaded_string_with_limit, Type::String.new(limit: 50) - attribute :non_existent_decimal, Type::Decimal.new - attribute :string_with_default, Type::String.new, default: 'the overloaded default' + attribute :overloaded_float, :integer + attribute :overloaded_string_with_limit, :string, limit: 50 + attribute :non_existent_decimal, :decimal + attribute :string_with_default, :string, default: 'the overloaded default' end class ChildOfOverloadedType < OverloadedType end class GrandchildOfOverloadedType < ChildOfOverloadedType - attribute :overloaded_float, Type::Float.new + attribute :overloaded_float, :float end class UnoverloadedType < ActiveRecord::Base @@ -124,5 +124,37 @@ module ActiveRecord assert_equal "from user", model.wibble end + + if current_adapter?(:PostgreSQLAdapter) + test "arrays types can be specified" do + klass = Class.new(OverloadedType) do + attribute :my_array, :string, limit: 50, array: true + attribute :my_int_array, :integer, array: true + end + + string_array = ConnectionAdapters::PostgreSQL::OID::Array.new( + Type::String.new(limit: 50)) + int_array = ConnectionAdapters::PostgreSQL::OID::Array.new( + Type::Integer.new) + refute_equal string_array, int_array + assert_equal string_array, klass.type_for_attribute("my_array") + assert_equal int_array, klass.type_for_attribute("my_int_array") + end + + test "range types can be specified" do + klass = Class.new(OverloadedType) do + attribute :my_range, :string, limit: 50, range: true + attribute :my_int_range, :integer, range: true + end + + string_range = ConnectionAdapters::PostgreSQL::OID::Range.new( + Type::String.new(limit: 50)) + int_range = ConnectionAdapters::PostgreSQL::OID::Range.new( + Type::Integer.new) + refute_equal string_range, int_range + assert_equal string_range, klass.type_for_attribute("my_range") + assert_equal int_range, klass.type_for_attribute("my_int_range") + end + end end end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 7c5939fc47..ef1173a2ba 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -903,8 +903,8 @@ class BasicsTest < ActiveRecord::TestCase class NumericData < ActiveRecord::Base self.table_name = 'numeric_data' - attribute :my_house_population, Type::Integer.new - attribute :atoms_in_universe, Type::Integer.new + attribute :my_house_population, :integer + attribute :atoms_in_universe, :integer end def test_big_decimal_conditions diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index c12fa03015..c05382598b 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -106,6 +106,15 @@ class EachTest < ActiveRecord::TestCase end end + def test_find_in_batches_should_end_at_the_end_option + assert_queries(6) do + Post.find_in_batches(batch_size: 1, end_at: 5) do |batch| + assert_kind_of Array, batch + assert_kind_of Post, batch.first + end + end + end + def test_find_in_batches_shouldnt_execute_query_unless_needed assert_queries(2) do Post.find_in_batches(:batch_size => @total) {|batch| assert_kind_of Array, batch } diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index f47568f2f5..f0393aa6b1 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -15,9 +15,9 @@ require 'models/treasure' class NumericData < ActiveRecord::Base self.table_name = 'numeric_data' - attribute :world_population, Type::Integer.new - attribute :my_house_population, Type::Integer.new - attribute :atoms_in_universe, Type::Integer.new + attribute :world_population, :integer + attribute :my_house_population, :integer + attribute :atoms_in_universe, :integer end class CalculationsTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/date_time_precision_test.rb b/activerecord/test/cases/date_time_precision_test.rb new file mode 100644 index 0000000000..720f10a9d3 --- /dev/null +++ b/activerecord/test/cases/date_time_precision_test.rb @@ -0,0 +1,102 @@ +require 'cases/helper' +require 'support/schema_dumping_helper' + +if ActiveRecord::Base.connection.supports_datetime_with_precision? +class DateTimePrecisionTest < ActiveRecord::TestCase + include SchemaDumpingHelper + self.use_transactional_fixtures = false + + class Foo < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + end + + teardown do + @connection.drop_table :foos, if_exists: true + end + + def test_datetime_data_type_with_precision + @connection.create_table(:foos, force: true) + @connection.add_column :foos, :created_at, :datetime, precision: 0 + @connection.add_column :foos, :updated_at, :datetime, precision: 5 + assert_equal 0, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_timestamps_helper_with_custom_precision + @connection.create_table(:foos, force: true) do |t| + t.timestamps precision: 4 + end + assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_passing_precision_to_datetime_does_not_set_limit + @connection.create_table(:foos, force: true) do |t| + t.timestamps precision: 4 + end + assert_nil activerecord_column_option('foos', 'created_at', 'limit') + assert_nil activerecord_column_option('foos', 'updated_at', 'limit') + end + + def test_invalid_datetime_precision_raises_error + assert_raises ActiveRecord::ActiveRecordError do + @connection.create_table(:foos, force: true) do |t| + t.timestamps precision: 7 + end + end + end + + def test_database_agrees_with_activerecord_about_precision + @connection.create_table(:foos, force: true) do |t| + t.timestamps precision: 4 + end + assert_equal 4, database_datetime_precision('foos', 'created_at') + assert_equal 4, database_datetime_precision('foos', 'updated_at') + end + + def test_formatting_datetime_according_to_precision + @connection.create_table(:foos, force: true) do |t| + t.datetime :created_at, precision: 0 + t.datetime :updated_at, precision: 4 + end + date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999) + Foo.create!(created_at: date, updated_at: date) + assert foo = Foo.find_by(created_at: date) + assert_equal 1, Foo.where(updated_at: date).count + assert_equal date.to_s, foo.created_at.to_s + assert_equal date.to_s, foo.updated_at.to_s + assert_equal 000000, foo.created_at.usec + assert_equal 999900, foo.updated_at.usec + end + + if current_adapter?(:PostgreSQLAdapter) + def test_datetime_precision_with_zero_should_be_dumped + @connection.create_table(:foos) do |t| + t.timestamps precision: 0 + end + output = dump_table_schema("foos") + assert_match %r{t\.datetime\s+"created_at",\s+precision: 0,\s+null: false$}, output + assert_match %r{t\.datetime\s+"updated_at",\s+precision: 0,\s+null: false$}, output + end + end + + private + + def database_datetime_precision(table_name, column_name) + results = @connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name = '#{table_name}'") + result = results.find do |result_hash| + result_hash["column_name"] == column_name + end + result && result["datetime_precision"].to_i + end + + def activerecord_column_option(tablename, column_name, option) + result = @connection.columns(tablename).find do |column| + column.name == column_name + end + result && result.send(option) + end +end +end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 192ba6f7cd..c2573ac72b 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -711,7 +711,7 @@ class DirtyTest < ActiveRecord::TestCase test "attribute_will_change! doesn't try to save non-persistable attributes" do klass = Class.new(ActiveRecord::Base) do self.table_name = 'people' - attribute :non_persisted_attribute, ActiveRecord::Type::String.new + attribute :non_persisted_attribute, :string end record = klass.new(first_name: "Sean") diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 346fcab6ea..e70d492efd 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -26,6 +26,49 @@ class EnumTest < ActiveRecord::TestCase assert_equal @book, Book.unread.first end + test "find via where with values" do + proposed, written = Book.statuses[:proposed], Book.statuses[:written] + + assert_equal @book, Book.where(status: proposed).first + refute_equal @book, Book.where(status: written).first + assert_equal @book, Book.where(status: [proposed]).first + refute_equal @book, Book.where(status: [written]).first + refute_equal @book, Book.where("status <> ?", proposed).first + assert_equal @book, Book.where("status <> ?", written).first + end + + test "find via where with symbols" do + assert_equal @book, Book.where(status: :proposed).first + refute_equal @book, Book.where(status: :written).first + assert_equal @book, Book.where(status: [:proposed]).first + refute_equal @book, Book.where(status: [:written]).first + refute_equal @book, Book.where.not(status: :proposed).first + assert_equal @book, Book.where.not(status: :written).first + end + + test "find via where with strings" do + assert_equal @book, Book.where(status: "proposed").first + refute_equal @book, Book.where(status: "written").first + assert_equal @book, Book.where(status: ["proposed"]).first + refute_equal @book, Book.where(status: ["written"]).first + refute_equal @book, Book.where.not(status: "proposed").first + assert_equal @book, Book.where.not(status: "written").first + end + + test "build from scope" do + assert Book.written.build.written? + refute Book.written.build.proposed? + end + + test "build from where" do + assert Book.where(status: Book.statuses[:written]).build.written? + refute Book.where(status: Book.statuses[:written]).build.proposed? + assert Book.where(status: :written).build.written? + refute Book.where(status: :written).build.proposed? + assert Book.where(status: "written").build.written? + refute Book.where(status: "written").build.proposed? + end + test "update by declaration" do @book.written! assert @book.written? @@ -129,19 +172,24 @@ class EnumTest < ActiveRecord::TestCase assert_equal "'unknown' is not a valid status", e.message end + test "NULL values from database should be casted to nil" do + Book.where(id: @book.id).update_all("status = NULL") + assert_nil @book.reload.status + end + test "assign nil value" do @book.status = nil - assert @book.status.nil? + assert_nil @book.status end test "assign empty string value" do @book.status = '' - assert @book.status.nil? + assert_nil @book.status end test "assign long empty string value" do @book.status = ' ' - assert @book.status.nil? + assert_nil @book.status end test "constant to access the mapping" do @@ -161,7 +209,11 @@ class EnumTest < ActiveRecord::TestCase end test "_before_type_cast returns the enum label (required for form fields)" do - assert_equal "proposed", @book.status_before_type_cast + if @book.status_came_from_user? + assert_equal "proposed", @book.status_before_type_cast + else + assert_equal "proposed", @book.status + end end test "reserved enum names" do diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 0a577fa2f5..f1f927852c 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -124,7 +124,7 @@ def enable_extension!(extension, connection) return connection.reconnect! if connection.extension_enabled?(extension) connection.enable_extension extension - connection.commit_db_transaction + connection.commit_db_transaction if connection.transaction_open? connection.reconnect! end diff --git a/activerecord/test/cases/migration/columns_test.rb b/activerecord/test/cases/migration/columns_test.rb index 54d3a729c3..6f65288ac0 100644 --- a/activerecord/test/cases/migration/columns_test.rb +++ b/activerecord/test/cases/migration/columns_test.rb @@ -65,7 +65,7 @@ module ActiveRecord if current_adapter?(:MysqlAdapter, :Mysql2Adapter) def test_mysql_rename_column_preserves_auto_increment rename_column "test_models", "id", "id_test" - assert_equal "auto_increment", connection.columns("test_models").find { |c| c.name == "id_test" }.extra + assert connection.columns("test_models").find { |c| c.name == "id_test" }.auto_increment? TestModel.reset_column_information ensure rename_column "test_models", "id_test", "id" diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index 8cba777fe2..3844b1a92e 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -256,6 +256,11 @@ module ActiveRecord assert_equal [:add_reference, [:table, :taggable, { polymorphic: true }], nil], add end + def test_invert_remove_reference_with_index_and_foreign_key + add = @recorder.inverse_of :remove_reference, [:table, :taggable, { index: true, foreign_key: true }] + assert_equal [:add_reference, [:table, :taggable, { index: true, foreign_key: true }], nil], add + end + def test_invert_remove_belongs_to_alias add = @recorder.inverse_of :remove_belongs_to, [:table, :user] assert_equal [:add_reference, [:table, :user], nil], add diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index 333fb7d4c6..7f4790bf3e 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -8,6 +8,7 @@ module ActiveRecord class ForeignKeyTest < ActiveRecord::TestCase include DdlHelper include SchemaDumpingHelper + include ActiveSupport::Testing::Stream class Rocket < ActiveRecord::Base end @@ -146,6 +147,27 @@ module ActiveRecord assert_equal :nullify, fk.on_update end + def test_foreign_key_exists + @connection.add_foreign_key :astronauts, :rockets + + assert @connection.foreign_key_exists?(:astronauts, :rockets) + assert_not @connection.foreign_key_exists?(:astronauts, :stars) + end + + def test_foreign_key_exists_by_column + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id" + + assert @connection.foreign_key_exists?(:astronauts, column: "rocket_id") + assert_not @connection.foreign_key_exists?(:astronauts, column: "star_id") + end + + def test_foreign_key_exists_by_name + @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk" + + assert @connection.foreign_key_exists?(:astronauts, name: "fancy_named_fk") + assert_not @connection.foreign_key_exists?(:astronauts, name: "other_fancy_named_fk") + end + def test_remove_foreign_key_inferes_column @connection.add_foreign_key :astronauts, :rockets @@ -221,17 +243,6 @@ module ActiveRecord silence_stream($stdout) { migration.migrate(:down) } end - private - - def silence_stream(stream) - old_stream = stream.dup - stream.reopen(IO::NULL) - stream.sync = true - yield - ensure - stream.reopen(old_stream) - old_stream.close - 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 99de7db70c..17ac72a109 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -10,8 +10,8 @@ module ActiveRecord end teardown do - @connection.drop_table("testings") if @connection.table_exists? "testings" - @connection.drop_table("testing_parents") if @connection.table_exists? "testing_parents" + @connection.drop_table "testings", if_exists: true + @connection.drop_table "testing_parents", if_exists: true end test "foreign keys can be created with the table" do @@ -95,6 +95,16 @@ module ActiveRecord end end end + + test "foreign key column can be removed" do + @connection.create_table :testings do |t| + t.references :testing_parent, index: true, foreign_key: true + end + + assert_difference "@connection.foreign_keys('testings').size", -1 do + @connection.remove_reference :testings, :testing_parent, foreign_key: true + end + end end end end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 6ea8b93be7..5f9fd5d527 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -14,9 +14,9 @@ require MIGRATIONS_ROOT + "/decimal/1_give_me_big_numbers" class BigNumber < ActiveRecord::Base unless current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter) - attribute :value_of_e, Type::Integer.new + attribute :value_of_e, :integer end - attribute :my_house_population, Type::Integer.new + attribute :my_house_population, :integer end class Reminder < ActiveRecord::Base; end @@ -119,10 +119,6 @@ class MigrationTest < ActiveRecord::TestCase end def test_create_table_with_force_true_does_not_drop_nonexisting_table - if Person.connection.table_exists?(:testings2) - Person.connection.drop_table :testings2 - end - # using a copy as we need the drop_table method to # continue to work for the ensure block of the test temp_conn = Person.connection.dup @@ -133,7 +129,7 @@ class MigrationTest < ActiveRecord::TestCase t.column :foo, :string end ensure - Person.connection.drop_table :testings2 rescue nil + Person.connection.drop_table :testings2, if_exists: true end def connection @@ -430,8 +426,6 @@ class MigrationTest < ActiveRecord::TestCase end def test_create_table_with_binary_column - Person.connection.drop_table :binary_testings rescue nil - assert_nothing_raised { Person.connection.create_table :binary_testings do |t| t.column "data", :binary, :null => false @@ -443,7 +437,7 @@ class MigrationTest < ActiveRecord::TestCase assert_nil data_column.default - Person.connection.drop_table :binary_testings rescue nil + Person.connection.drop_table :binary_testings, if_exists: true end unless mysql_enforcing_gtid_consistency? @@ -721,6 +715,8 @@ if ActiveRecord::Base.connection.supports_bulk_alter? end class CopyMigrationsTest < ActiveRecord::TestCase + include ActiveSupport::Testing::Stream + def setup end @@ -930,23 +926,4 @@ class CopyMigrationsTest < ActiveRecord::TestCase ActiveRecord::Base.logger = old end - private - - def quietly - silence_stream(STDOUT) do - silence_stream(STDERR) do - yield - end - end - end - - def silence_stream(stream) - old_stream = stream.dup - stream.reopen(IO::NULL) - stream.sync = true - yield - ensure - stream.reopen(old_stream) - old_stream.close - end end diff --git a/activerecord/test/cases/multiparameter_attributes_test.rb b/activerecord/test/cases/multiparameter_attributes_test.rb index 4aaf6f8b5f..ae18573126 100644 --- a/activerecord/test/cases/multiparameter_attributes_test.rb +++ b/activerecord/test/cases/multiparameter_attributes_test.rb @@ -199,6 +199,7 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes with_timezone_config default: :utc, aware_attributes: true, zone: -28800 do + Topic.reset_column_information attributes = { "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" @@ -209,6 +210,8 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on.time assert_equal Time.zone, topic.written_on.time_zone end + ensure + Topic.reset_column_information end def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes_false @@ -227,6 +230,7 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase def test_multiparameter_attributes_on_time_with_skip_time_zone_conversion_for_attributes with_timezone_config default: :utc, aware_attributes: true, zone: -28800 do Topic.skip_time_zone_conversion_for_attributes = [:written_on] + Topic.reset_column_information attributes = { "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" @@ -238,12 +242,14 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase end ensure Topic.skip_time_zone_conversion_for_attributes = [] + Topic.reset_column_information end # Oracle does not have a TIME datatype. unless current_adapter?(:OracleAdapter) def test_multiparameter_attributes_on_time_only_column_with_time_zone_aware_attributes_does_not_do_time_zone_conversion with_timezone_config default: :utc, aware_attributes: true, zone: -28800 do + Topic.reset_column_information attributes = { "bonus_time(1i)" => "2000", "bonus_time(2i)" => "1", "bonus_time(3i)" => "1", "bonus_time(4i)" => "16", "bonus_time(5i)" => "24" @@ -253,6 +259,8 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase assert_equal Time.zone.local(2000, 1, 1, 16, 24, 0), topic.bonus_time assert_not topic.bonus_time.utc? end + ensure + Topic.reset_column_information end end diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb index 15c60d5562..f9bc266e84 100644 --- a/activerecord/test/cases/multiple_db_test.rb +++ b/activerecord/test/cases/multiple_db_test.rb @@ -93,14 +93,14 @@ class MultipleDbTest < ActiveRecord::TestCase assert_not_equal Entrant.arel_engine.connection, Course.arel_engine.connection end - def test_count_on_custom_connection - ActiveRecord::Base.remove_connection - assert_equal 1, College.count - ensure - ActiveRecord::Base.establish_connection :arunit - end - unless in_memory_db? + def test_count_on_custom_connection + ActiveRecord::Base.remove_connection + assert_equal 1, College.count + ensure + ActiveRecord::Base.establish_connection :arunit + end + def test_associations_should_work_when_model_has_no_connection begin ActiveRecord::Base.remove_connection diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index ad09340518..6d91f96bf6 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -46,28 +46,28 @@ module ActiveRecord def test_quoted_time_utc with_timezone_config default: :utc do - t = Time.now + t = Time.now.change(usec: 0) assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) end end def test_quoted_time_local with_timezone_config default: :local do - t = Time.now + t = Time.now.change(usec: 0) assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t) end end def test_quoted_time_crazy with_timezone_config default: :asdfasdf do - t = Time.now + t = Time.now.change(usec: 0) assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t) end end def test_quoted_datetime_utc with_timezone_config default: :utc do - t = DateTime.now + t = Time.now.change(usec: 0).to_datetime assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) end end @@ -76,7 +76,7 @@ module ActiveRecord # DateTime doesn't define getlocal, so make sure it does nothing def test_quoted_datetime_local with_timezone_config default: :local do - t = DateTime.now + t = Time.now.change(usec: 0).to_datetime assert_equal t.to_s(:db), @quoter.quoted_date(t) end end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 194faa9473..c9c05b75a6 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -168,6 +168,22 @@ module ActiveRecord assert_raises(ArgumentError) { Relation::HashMerger.new(nil, omg: 'lol') } end + test 'merging nil or false raises' do + relation = Relation.new(FakeKlass, :b, nil) + + e = assert_raises(ArgumentError) do + relation = relation.merge nil + end + + assert_equal 'invalid argument: nil.', e.message + + e = assert_raises(ArgumentError) do + relation = relation.merge false + end + + assert_equal 'invalid argument: false.', e.message + end + test '#values returns a dup of the values' do relation = Relation.new(FakeKlass, :b, nil).where! :foo values = relation.values diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 5c5ab499a0..dec3a37f42 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -342,7 +342,9 @@ class RelationTest < ActiveRecord::TestCase assert_equal 0, Developer.none.size assert_equal 0, Developer.none.count assert_equal true, Developer.none.empty? + assert_equal true, Developer.none.none? assert_equal false, Developer.none.any? + assert_equal false, Developer.none.one? assert_equal false, Developer.none.many? end end @@ -1102,6 +1104,38 @@ class RelationTest < ActiveRecord::TestCase assert ! posts.limit(1).many? end + def test_none? + posts = Post.all + assert_queries(1) do + assert ! posts.none? # Uses COUNT() + end + + assert ! posts.loaded? + + assert_queries(1) do + assert posts.none? {|p| p.id < 0 } + assert ! posts.none? {|p| p.id == 1 } + end + + assert posts.loaded? + end + + def test_one + posts = Post.all + assert_queries(1) do + assert ! posts.one? # Uses COUNT() + end + + assert ! posts.loaded? + + assert_queries(1) do + assert ! posts.one? {|p| p.id < 3 } + assert posts.one? {|p| p.id == 1 } + end + + assert posts.loaded? + 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 c8ea702488..bafc9fa81b 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -73,10 +73,10 @@ class SchemaDumperTest < ActiveRecord::TestCase next if column_set.empty? lengths = column_set.map do |column| - if match = column.match(/t\.(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean|uuid|point)\s+"/) + if match = column.match(/t\.(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean|xml|uuid|point)\s+"/) match[0].length end - end + end.compact assert_equal 1, lengths.uniq.length end diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb index 02b32abebf..4bfffbe9c6 100644 --- a/activerecord/test/cases/scoping/relation_scoping_test.rb +++ b/activerecord/test/cases/scoping/relation_scoping_test.rb @@ -208,6 +208,12 @@ class RelationScopingTest < ActiveRecord::TestCase assert_equal [], DeveloperFilteredOnJoins.all assert_not_equal [], Developer.all end + + def test_current_scope_does_not_pollute_other_subclasses + Post.none.scoping do + assert StiPost.all.any? + end + end end class NestedRelationScopingTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/secure_token_test.rb b/activerecord/test/cases/secure_token_test.rb index 3f7455d12d..e731443fc2 100644 --- a/activerecord/test/cases/secure_token_test.rb +++ b/activerecord/test/cases/secure_token_test.rb @@ -22,4 +22,11 @@ class SecureTokenTest < ActiveRecord::TestCase assert_not_equal @user.token, old_token assert_not_equal @user.auth_token, old_auth_token end + + def test_token_value_not_overwritten_when_present + @user.token = "custom-secure-token" + @user.save + + assert_equal @user.token, "custom-secure-token" + end end diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb index 5ba17359f0..e0b01ae8e0 100644 --- a/activerecord/test/cases/test_case.rb +++ b/activerecord/test/cases/test_case.rb @@ -1,10 +1,13 @@ require 'active_support/test_case' +require 'active_support/testing/stream' module ActiveRecord # = Active Record Test Case # # Defines some test assertions to test against SQL queries. class TestCase < ActiveSupport::TestCase #:nodoc: + include ActiveSupport::Testing::Stream + def teardown SQLCounter.clear_log end @@ -13,23 +16,6 @@ module ActiveRecord assert_equal expected.to_s, actual.to_s, message end - def capture(stream) - stream = stream.to_s - captured_stream = Tempfile.new(stream) - stream_io = eval("$#{stream}") - origin_stream = stream_io.dup - stream_io.reopen(captured_stream) - - yield - - stream_io.rewind - return captured_stream.read - ensure - captured_stream.close - captured_stream.unlink - stream_io.reopen(origin_stream) - end - def capture_sql SQLCounter.clear_log yield diff --git a/activerecord/test/cases/time_precision_test.rb b/activerecord/test/cases/time_precision_test.rb new file mode 100644 index 0000000000..23422fd50a --- /dev/null +++ b/activerecord/test/cases/time_precision_test.rb @@ -0,0 +1,65 @@ +require 'cases/helper' + +if ActiveRecord::Base.connection.supports_datetime_with_precision? +class TimePrecisionTest < ActiveRecord::TestCase + setup do + @connection = ActiveRecord::Base.connection + end + + teardown do + @connection.drop_table :foos, if_exists: true + end + + def test_time_data_type_with_precision + @connection.create_table(:foos, force: true) + @connection.add_column :foos, :start, :time, precision: 3 + @connection.add_column :foos, :finish, :time, precision: 6 + assert_equal 3, activerecord_column_option('foos', 'start', 'precision') + assert_equal 6, activerecord_column_option('foos', 'finish', 'precision') + end + + def test_passing_precision_to_time_does_not_set_limit + @connection.create_table(:foos, force: true) do |t| + t.time :start, precision: 3 + t.time :finish, precision: 6 + end + assert_nil activerecord_column_option('foos', 'start', 'limit') + assert_nil activerecord_column_option('foos', 'finish', 'limit') + end + + def test_invalid_time_precision_raises_error + assert_raises ActiveRecord::ActiveRecordError do + @connection.create_table(:foos, force: true) do |t| + t.time :start, precision: 7 + t.time :finish, precision: 7 + end + end + end + + def test_database_agrees_with_activerecord_about_precision + @connection.create_table(:foos, force: true) do |t| + t.time :start, precision: 2 + t.time :finish, precision: 4 + end + assert_equal 2, database_datetime_precision('foos', 'start') + assert_equal 4, database_datetime_precision('foos', 'finish') + end + + private + + def database_datetime_precision(table_name, column_name) + results = @connection.exec_query("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name = '#{table_name}'") + result = results.find do |result_hash| + result_hash["column_name"] == column_name + end + result && result["datetime_precision"].to_i + end + + def activerecord_column_option(tablename, column_name, option) + result = @connection.columns(tablename).find do |column| + column.name == column_name + end + result && result.send(option) + end +end +end diff --git a/activerecord/test/cases/type/adapter_specific_registry_test.rb b/activerecord/test/cases/type/adapter_specific_registry_test.rb new file mode 100644 index 0000000000..8b836b4793 --- /dev/null +++ b/activerecord/test/cases/type/adapter_specific_registry_test.rb @@ -0,0 +1,133 @@ +require "cases/helper" + +module ActiveRecord + class AdapterSpecificRegistryTest < ActiveRecord::TestCase + test "a class can be registered for a symbol" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, ::String) + registry.register(:bar, ::Array) + + assert_equal "", registry.lookup(:foo) + assert_equal [], registry.lookup(:bar) + end + + test "a block can be registered" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo) do |*args| + [*args, "block for foo"] + end + registry.register(:bar) do |*args| + [*args, "block for bar"] + end + + assert_equal [:foo, 1, "block for foo"], registry.lookup(:foo, 1) + assert_equal [:foo, 2, "block for foo"], registry.lookup(:foo, 2) + assert_equal [:bar, 1, 2, 3, "block for bar"], registry.lookup(:bar, 1, 2, 3) + end + + test "filtering by adapter" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String, adapter: :sqlite3) + registry.register(:foo, Array, adapter: :postgresql) + + assert_equal "", registry.lookup(:foo, adapter: :sqlite3) + assert_equal [], registry.lookup(:foo, adapter: :postgresql) + end + + test "an error is raised if both a generic and adapter specific type match" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String) + registry.register(:foo, Array, adapter: :postgresql) + + assert_raises TypeConflictError do + registry.lookup(:foo, adapter: :postgresql) + end + assert_equal "", registry.lookup(:foo, adapter: :sqlite3) + end + + test "a generic type can explicitly override an adapter specific type" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String, override: true) + registry.register(:foo, Array, adapter: :postgresql) + + assert_equal "", registry.lookup(:foo, adapter: :postgresql) + assert_equal "", registry.lookup(:foo, adapter: :sqlite3) + end + + test "a generic type can explicitly allow an adapter type to be used instead" do + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String, override: false) + registry.register(:foo, Array, adapter: :postgresql) + + assert_equal [], registry.lookup(:foo, adapter: :postgresql) + assert_equal "", registry.lookup(:foo, adapter: :sqlite3) + end + + test "a reasonable error is given when no type is found" do + registry = Type::AdapterSpecificRegistry.new + + e = assert_raises(ArgumentError) do + registry.lookup(:foo) + end + + assert_equal "Unknown type :foo", e.message + end + + test "construct args are passed to the type" do + type = Struct.new(:args) + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, type) + + assert_equal type.new, registry.lookup(:foo) + assert_equal type.new(:ordered_arg), registry.lookup(:foo, :ordered_arg) + assert_equal type.new(keyword: :arg), registry.lookup(:foo, keyword: :arg) + assert_equal type.new(keyword: :arg), registry.lookup(:foo, keyword: :arg, adapter: :postgresql) + end + + test "registering a modifier" do + decoration = Struct.new(:value) + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String) + registry.register(:bar, Hash) + registry.add_modifier({ array: true }, decoration) + + assert_equal decoration.new(""), registry.lookup(:foo, array: true) + assert_equal decoration.new({}), registry.lookup(:bar, array: true) + assert_equal "", registry.lookup(:foo) + end + + test "registering multiple modifiers" do + decoration = Struct.new(:value) + other_decoration = Struct.new(:value) + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, String) + registry.add_modifier({ array: true }, decoration) + registry.add_modifier({ range: true }, other_decoration) + + assert_equal "", registry.lookup(:foo) + assert_equal decoration.new(""), registry.lookup(:foo, array: true) + assert_equal other_decoration.new(""), registry.lookup(:foo, range: true) + assert_equal( + decoration.new(other_decoration.new("")), + registry.lookup(:foo, array: true, range: true) + ) + end + + test "registering adapter specific modifiers" do + decoration = Struct.new(:value) + type = Struct.new(:args) + registry = Type::AdapterSpecificRegistry.new + registry.register(:foo, type) + registry.add_modifier({ array: true }, decoration, adapter: :postgresql) + + assert_equal( + decoration.new(type.new(keyword: :arg)), + registry.lookup(:foo, array: true, adapter: :postgresql, keyword: :arg) + ) + assert_equal( + type.new(array: true), + registry.lookup(:foo, array: true, adapter: :sqlite3) + ) + end + end +end diff --git a/activerecord/test/cases/type/integer_test.rb b/activerecord/test/cases/type/integer_test.rb index 0c60f0690c..1e836f2142 100644 --- a/activerecord/test/cases/type/integer_test.rb +++ b/activerecord/test/cases/type/integer_test.rb @@ -113,7 +113,7 @@ module ActiveRecord test "values which are out of range can be re-assigned" do klass = Class.new(ActiveRecord::Base) do self.table_name = 'posts' - attribute :foo, Type::Integer.new + attribute :foo, :integer end model = klass.new diff --git a/activerecord/test/cases/type_test.rb b/activerecord/test/cases/type_test.rb new file mode 100644 index 0000000000..d45a9b3141 --- /dev/null +++ b/activerecord/test/cases/type_test.rb @@ -0,0 +1,39 @@ +require "cases/helper" + +class TypeTest < ActiveRecord::TestCase + setup do + @old_registry = ActiveRecord::Type.registry + ActiveRecord::Type.registry = ActiveRecord::Type::AdapterSpecificRegistry.new + end + + teardown do + ActiveRecord::Type.registry = @old_registry + end + + test "registering a new type" do + type = Struct.new(:args) + ActiveRecord::Type.register(:foo, type) + + assert_equal type.new(:arg), ActiveRecord::Type.lookup(:foo, :arg) + end + + test "looking up a type for a specific adapter" do + type = Struct.new(:args) + pgtype = Struct.new(:args) + ActiveRecord::Type.register(:foo, type, override: false) + ActiveRecord::Type.register(:foo, pgtype, adapter: :postgresql) + + assert_equal type.new, ActiveRecord::Type.lookup(:foo, adapter: :sqlite) + assert_equal pgtype.new, ActiveRecord::Type.lookup(:foo, adapter: :postgresql) + end + + test "lookup defaults to the current adapter" do + current_adapter = ActiveRecord::Base.connection.adapter_name.downcase.to_sym + type = Struct.new(:args) + adapter_type = Struct.new(:args) + ActiveRecord::Type.register(:foo, type, override: false) + ActiveRecord::Type.register(:foo, adapter_type, adapter: current_adapter) + + assert_equal adapter_type.new, ActiveRecord::Type.lookup(:foo) + end +end diff --git a/activerecord/test/cases/types_test.rb b/activerecord/test/cases/types_test.rb index d35d34ff2d..34b6f2e8a5 100644 --- a/activerecord/test/cases/types_test.rb +++ b/activerecord/test/cases/types_test.rb @@ -108,16 +108,6 @@ module ActiveRecord assert_not_equal Type::Value.new(precision: 1), Type::Value.new(precision: 2) end - if current_adapter?(:SQLite3Adapter) - def test_binary_encoding - type = SQLite3Binary.new - utf8_string = "a string".encode(Encoding::UTF_8) - type_cast = type.type_cast_from_user(utf8_string) - - assert_equal Encoding::ASCII_8BIT, type_cast.encoding - end - end - def test_attributes_which_are_invalid_for_database_can_still_be_reassigned type_which_cannot_go_to_the_database = Type::Value.new def type_which_cannot_go_to_the_database.type_cast_for_database(*) diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index b0f34e5f47..f4f316f393 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -150,7 +150,7 @@ class ValidationsTest < ActiveRecord::TestCase def test_numericality_validation_with_mutation Topic.class_eval do - attribute :wibble, ActiveRecord::Type::String.new + attribute :wibble, :string validates_numericality_of :wibble, only_integer: true end |