diff options
author | Rafael França <rafaelmfranca@gmail.com> | 2016-12-29 02:18:38 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-29 02:18:38 -0500 |
commit | eb6a6141a66e052deb58580448d7c0fa6aa675ba (patch) | |
tree | 0017a57044ec8e466c97cc6b7879d39caa6c1ffa /activerecord/test | |
parent | 447e1a48811fa053e8bef954376d1ad47bdb5cef (diff) | |
parent | fcec126eaa4f835c837bc75efa78008667b2ec5b (diff) | |
download | rails-eb6a6141a66e052deb58580448d7c0fa6aa675ba.tar.gz rails-eb6a6141a66e052deb58580448d7c0fa6aa675ba.tar.bz2 rails-eb6a6141a66e052deb58580448d7c0fa6aa675ba.zip |
Merge branch 'master' into clear_all_environments_log_by_default
Diffstat (limited to 'activerecord/test')
129 files changed, 2032 insertions, 671 deletions
diff --git a/activerecord/test/active_record/connection_adapters/fake_adapter.rb b/activerecord/test/active_record/connection_adapters/fake_adapter.rb index 43c817e057..b0d8050721 100644 --- a/activerecord/test/active_record/connection_adapters/fake_adapter.rb +++ b/activerecord/test/active_record/connection_adapters/fake_adapter.rb @@ -9,7 +9,7 @@ module ActiveRecord class FakeAdapter < AbstractAdapter attr_accessor :data_sources, :primary_keys - @columns = Hash.new { |h,k| h[k] = [] } + @columns = Hash.new { |h, k| h[k] = [] } class << self attr_reader :columns end diff --git a/activerecord/test/assets/schema_dump_5_1.yml b/activerecord/test/assets/schema_dump_5_1.yml new file mode 100644 index 0000000000..f37977daf2 --- /dev/null +++ b/activerecord/test/assets/schema_dump_5_1.yml @@ -0,0 +1,345 @@ +--- !ruby/object:ActiveRecord::ConnectionAdapters::SchemaCache +columns: + posts: + - &1 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: id + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: INTEGER + type: :integer + limit: + precision: + scale: + 'null': false + default: + default_function: + collation: + comment: + - &2 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: author_id + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: + default_function: + collation: + comment: + - &3 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: title + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: varchar + type: :string + limit: + precision: + scale: + 'null': false + default: + default_function: + collation: + comment: + - &4 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: body + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: text + type: :text + limit: + precision: + scale: + 'null': false + default: + default_function: + collation: + comment: + - &5 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: type + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: varchar + type: :string + limit: + precision: + scale: + 'null': true + default: + default_function: + collation: + comment: + - &6 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: comments_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: + - &7 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: taggings_with_delete_all_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: + - &8 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: taggings_with_destroy_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: + - &9 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: tags_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: + - &10 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: tags_with_destroy_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: + - &11 !ruby/object:ActiveRecord::ConnectionAdapters::Column + name: tags_with_nullify_count + table_name: posts + sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata + sql_type: integer + type: :integer + limit: + precision: + scale: + 'null': true + default: '0' + default_function: + collation: + comment: +columns_hash: + posts: + id: *1 + author_id: *2 + title: *3 + body: *4 + type: *5 + comments_count: *6 + taggings_with_delete_all_count: *7 + taggings_with_destroy_count: *8 + tags_count: *9 + tags_with_destroy_count: *10 + tags_with_nullify_count: *11 +primary_keys: + posts: id +data_sources: + ar_internal_metadata: true + table_with_autoincrement: true + accounts: true + admin_accounts: true + admin_users: true + aircraft: true + articles: true + articles_magazines: true + articles_tags: true + audit_logs: true + authors: true + author_addresses: true + author_favorites: true + auto_id_tests: true + binaries: true + birds: true + books: true + booleans: true + bulbs: true + CamelCase: true + cars: true + carriers: true + categories: true + categories_posts: true + categorizations: true + citations: true + clubs: true + collections: true + colnametests: true + columns: true + comments: true + companies: true + content: true + content_positions: true + vegetables: true + computers: true + computers_developers: true + contracts: true + customers: true + customer_carriers: true + dashboards: true + developers: true + developers_projects: true + dog_lovers: true + dogs: true + doubloons: true + edges: true + engines: true + entrants: true + essays: true + events: true + eyes: true + funny_jokes: true + cold_jokes: true + friendships: true + goofy_string_id: true + having: true + guids: true + guitars: true + inept_wizards: true + integer_limits: true + invoices: true + iris: true + items: true + jobs: true + jobs_pool: true + keyboards: true + legacy_things: true + lessons: true + lessons_students: true + students: true + lint_models: true + line_items: true + lions: true + lock_without_defaults: true + lock_without_defaults_cust: true + magazines: true + mateys: true + members: true + member_details: true + member_friends: true + memberships: true + member_types: true + mentors: true + minivans: true + minimalistics: true + mixed_case_monkeys: true + mixins: true + movies: true + notifications: true + numeric_data: true + orders: true + organizations: true + owners: true + paint_colors: true + paint_textures: true + parrots: true + parrots_pirates: true + parrots_treasures: true + people: true + peoples_treasures: true + personal_legacy_things: true + pets: true + pets_treasures: true + pirates: true + posts: true + serialized_posts: true + images: true + price_estimates: true + products: true + product_types: true + projects: true + randomly_named_table1: true + randomly_named_table2: true + randomly_named_table3: true + ratings: true + readers: true + references: true + shape_expressions: true + ships: true + ship_parts: true + prisoners: true + shop_accounts: true + speedometers: true + sponsors: true + string_key_objects: true + subscribers: true + subscriptions: true + tags: true + taggings: true + tasks: true + topics: true + toys: true + traffic_lights: true + treasures: true + tuning_pegs: true + tyres: true + variants: true + vertices: true + warehouse-things: true + circles: true + squares: true + triangles: true + non_poly_ones: true + non_poly_twos: true + men: true + faces: true + interests: true + zines: true + wheels: true + countries: true + treaties: true + countries_treaties: true + liquid: true + molecules: true + electrons: true + weirds: true + nodes: true + trees: true + hotels: true + departments: true + cake_designers: true + drink_designers: true + chefs: true + recipes: true + records: true + overloaded_types: true + users: true + test_with_keyword_column_name: true + fk_test_has_pk: true + fk_test_has_fk: true +version: 0 diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 8fa0645b0f..3fce0a1df1 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -42,8 +42,10 @@ module ActiveRecord def test_table_exists? ActiveSupport::Deprecation.silence do assert @connection.table_exists?("accounts") - assert !@connection.table_exists?("nonexistingtable") - assert !@connection.table_exists?(nil) + assert @connection.table_exists?(:accounts) + assert_not @connection.table_exists?("nonexistingtable") + assert_not @connection.table_exists?("'") + assert_not @connection.table_exists?(nil) end end @@ -63,26 +65,22 @@ module ActiveRecord assert @connection.data_source_exists?("accounts") assert @connection.data_source_exists?(:accounts) assert_not @connection.data_source_exists?("nonexistingtable") + assert_not @connection.data_source_exists?("'") assert_not @connection.data_source_exists?(nil) end def test_indexes idx_name = "accounts_idx" - if @connection.respond_to?(:indexes) - indexes = @connection.indexes("accounts") - assert indexes.empty? - - @connection.add_index :accounts, :firm_id, name: idx_name - indexes = @connection.indexes("accounts") - assert_equal "accounts", indexes.first.table - assert_equal idx_name, indexes.first.name - assert !indexes.first.unique - assert_equal ["firm_id"], indexes.first.columns - else - warn "#{@connection.class} does not respond to #indexes" - end + indexes = @connection.indexes("accounts") + assert indexes.empty? + @connection.add_index :accounts, :firm_id, name: idx_name + indexes = @connection.indexes("accounts") + assert_equal "accounts", indexes.first.table + assert_equal idx_name, indexes.first.name + assert !indexes.first.unique + assert_equal ["firm_id"], indexes.first.columns ensure @connection.remove_index(:accounts, name: idx_name) rescue nil end @@ -184,6 +182,14 @@ module ActiveRecord assert_not_nil error.cause end + def test_not_null_violations_are_translated_to_specific_exception + error = assert_raises(ActiveRecord::NotNullViolation) do + Post.create + end + + assert_not_nil error.cause + end + unless current_adapter?(:SQLite3Adapter) def test_foreign_key_violations_are_translated_to_specific_exception error = assert_raises(ActiveRecord::InvalidForeignKey) do @@ -220,6 +226,14 @@ module ActiveRecord assert_not_nil error.cause end + + def test_numeric_value_out_of_ranges_are_translated_to_specific_exception + error = assert_raises(ActiveRecord::RangeError) do + Book.connection.create("INSERT INTO books(author_id) VALUES (2147483648)") + end + + assert_not_nil error.cause + end end def test_disable_referential_integrity @@ -271,13 +285,13 @@ module ActiveRecord unless current_adapter?(:PostgreSQLAdapter) def test_log_invalid_encoding - error = assert_raise ActiveRecord::StatementInvalid do + error = assert_raises RuntimeError do @connection.send :log, "SELECT 'ы' FROM DUAL" do raise "ы".force_encoding(Encoding::ASCII_8BIT) end end - assert_not_nil error.cause + assert_not_nil error.message end end diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb index a70eb5a094..2a528b2cb1 100644 --- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb @@ -28,12 +28,15 @@ class Mysql2ActiveSchemaTest < ActiveRecord::Mysql2TestCase expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15)) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: 15) + assert_equal expected, add_index(:people, ["last_name", "first_name"], length: 15) expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15 }) + assert_equal expected, add_index(:people, ["last_name", "first_name"], length: { last_name: 15 }) expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15, first_name: 10 }) + assert_equal expected, add_index(:people, ["last_name", :first_name], length: { last_name: 15, "first_name" => 10 }) %w(SPATIAL FULLTEXT UNIQUE).each do |type| expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) " diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 8d8955e5c9..c1de2218e2 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -65,18 +65,18 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase def test_execute_after_disconnect @connection.disconnect! - error = assert_raise(ActiveRecord::StatementInvalid) do + + assert_raise(ActiveRecord::StatementInvalid) do @connection.execute("SELECT 1") end - assert_match(/closed MySQL connection/, error.message) end def test_quote_after_disconnect @connection.disconnect! - error = assert_raise(Mysql2::Error) do + + assert_raise(Mysql2::Error) do @connection.quote("string") end - assert_match(/closed MySQL connection/, error.message) end def test_active_after_disconnect @@ -122,7 +122,7 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase 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] + assert_equal (Mysql2::Client::COMPRESS | Mysql2::Client::FOUND_ROWS), ActiveRecord::Base.connection.raw_connection.query_options[:flags] end end @@ -186,7 +186,7 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase "expected release_advisory_lock to return false when there was no lock to release" end - protected + private def test_lock_free(lock_name) @connection.select_value("SELECT IS_FREE_LOCK(#{@connection.quote(lock_name)})") == 1 diff --git a/activerecord/test/cases/adapters/mysql2/json_test.rb b/activerecord/test/cases/adapters/mysql2/json_test.rb index 630cdb36a4..6954006003 100644 --- a/activerecord/test/cases/adapters/mysql2/json_test.rb +++ b/activerecord/test/cases/adapters/mysql2/json_test.rb @@ -67,8 +67,8 @@ if ActiveRecord::Base.connection.supports_json? assert_equal({ "a_key" => "a_value" }, type.deserialize(data)) assert_equal({}, type.deserialize("{}")) - assert_equal({ "key"=>nil }, type.deserialize('{"key": null}')) - assert_equal({ "c"=>"}",'"a"'=>'b "a b' }, type.deserialize(%q({"c":"}", "\"a\"":"b \"a b"}))) + assert_equal({ "key" => nil }, type.deserialize('{"key": null}')) + assert_equal({ "c" => "}", '"a"' => 'b "a b' }, type.deserialize(%q({"c":"}", "\"a\"":"b \"a b"}))) end def test_rewrite @@ -87,13 +87,13 @@ if ActiveRecord::Base.connection.supports_json? def test_select_multikey @connection.execute %q|insert into json_data_type (payload) VALUES ('{"k1":"v1", "k2":"v2", "k3":[1,2,3]}')| x = JsonDataType.first - assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1,2,3] }, x.payload) + assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1, 2, 3] }, x.payload) end def test_null_json @connection.execute "insert into json_data_type (payload) VALUES(null)" x = JsonDataType.first - assert_equal(nil, x.payload) + assert_nil(x.payload) end def test_select_array_json_value @@ -104,17 +104,17 @@ if ActiveRecord::Base.connection.supports_json? def test_select_nil_json_after_create json = JsonDataType.create(payload: nil) - x = JsonDataType.where(payload:nil).first + x = JsonDataType.where(payload: nil).first assert_equal(json, x) end def test_select_nil_json_after_update json = JsonDataType.create(payload: "foo") - x = JsonDataType.where(payload:nil).first - assert_equal(nil, x) + x = JsonDataType.where(payload: nil).first + assert_nil(x) json.update_attributes payload: nil - x = JsonDataType.where(payload:nil).first + x = JsonDataType.where(payload: nil).first assert_equal(json.reload, x) end diff --git a/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb b/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb new file mode 100644 index 0000000000..5d3125c2be --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb @@ -0,0 +1,60 @@ +require "cases/helper" + +class MysqlLegacyMigrationTest < ActiveRecord::Mysql2TestCase + self.use_transactional_tests = false + + class GenerateTableWithoutBigint < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + @connection = ActiveRecord::Base.connection + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigint.new(nil, 1)] + + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + @connection.drop_table("legacy_integer_pk") + @connection.drop_table("override_pk") + ActiveRecord::SchemaMigration.delete_all rescue nil + super + end + + def test_create_table_uses_integer_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "int(11)", sql_type_for(col) + assert col.auto_increment? + end + + def test_create_tables_respects_pk_column_type_override + col = column(:override_pk, :id) + assert_equal "bigint(20)", sql_type_for(col) + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection + .columns(table_name.to_s) + .detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end +end diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 69336eb906..aab3dcb724 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -65,6 +65,19 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.columns_for_distinct("posts.id", [order]) end + def test_errors_for_bigint_fks_on_integer_pk_table + # table old_cars has primary key of integer + + error = assert_raises(ActiveRecord::MismatchedForeignKey) do + @conn.add_reference :engines, :old_car + @conn.add_foreign_key :engines, :old_cars + end + + assert_match "Column `old_car_id` on table `engines` has a type of `bigint(20)`", error.message + assert_not_nil error.cause + @conn.exec_query("ALTER TABLE engines DROP COLUMN old_car_id") + end + private def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block) diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb index 776549eb7a..2c778b1150 100644 --- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb @@ -30,11 +30,11 @@ class Mysql2ReservedWordTest < ActiveRecord::Mysql2TestCase # we call execute directly here (and do similar below) because ActiveRecord::Base#create_table() # will fail with these table names if these test cases fail - create_tables_directly "group"=>"id int auto_increment primary key, `order` varchar(255), select_id int", - "select"=>"id int auto_increment primary key", - "values"=>"id int auto_increment primary key, group_id int", - "distinct"=>"id int auto_increment primary key", - "distinct_select"=>"distinct_id int, select_id int" + create_tables_directly "group" => "id int auto_increment primary key, `order` varchar(255), select_id int", + "select" => "id int auto_increment primary key", + "values" => "id int auto_increment primary key, group_id int", + "distinct" => "id int auto_increment primary key", + "distinct_select" => "distinct_id int, select_id int" end teardown do @@ -143,7 +143,7 @@ class Mysql2ReservedWordTest < ActiveRecord::Mysql2TestCase end # custom create table, uses execute on connection to create a table, note: escapes table_name, does NOT escape columns - def create_tables_directly (tables, connection = @connection) + def create_tables_directly(tables, connection = @connection) tables.each do |table_name, column_properties| connection.execute("CREATE TABLE `#{table_name}` ( #{column_properties} )") end diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb index aea930cfe6..1fad5585de 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb @@ -76,7 +76,7 @@ module ActiveRecord table = "key_tests" indexes = @connection.indexes(table).sort_by(&:name) - assert_equal 3,indexes.size + assert_equal 3, indexes.size index_a = indexes.select { |i| i.name == index_a_name }[0] index_b = indexes.select { |i| i.name == index_b_name }[0] diff --git a/activerecord/test/cases/adapters/mysql2/transaction_test.rb b/activerecord/test/cases/adapters/mysql2/transaction_test.rb index edd5353ee3..16101e38cb 100644 --- a/activerecord/test/cases/adapters/mysql2/transaction_test.rb +++ b/activerecord/test/cases/adapters/mysql2/transaction_test.rb @@ -10,6 +10,8 @@ module ActiveRecord end setup do + @abort, Thread.abort_on_exception = Thread.abort_on_exception, false + @connection = ActiveRecord::Base.connection @connection.clear_cache! @@ -25,30 +27,34 @@ module ActiveRecord teardown do @connection.drop_table "samples", if_exists: true + + Thread.abort_on_exception = @abort end test "raises Deadlocked when a deadlock is encountered" do assert_raises(ActiveRecord::Deadlocked) do + barrier = Concurrent::CyclicBarrier.new(2) + s1 = Sample.create value: 1 s2 = Sample.create value: 2 thread = Thread.new do Sample.transaction do s1.lock! - sleep 1 + barrier.wait s2.update_attributes value: 1 end end - sleep 0.5 - - Sample.transaction do - s2.lock! - sleep 1 - s1.update_attributes value: 2 + begin + Sample.transaction do + s2.lock! + barrier.wait + s1.update_attributes value: 2 + end + ensure + thread.join end - - thread.join end end end diff --git a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb index 3df11ce11b..a0823be143 100644 --- a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb +++ b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb @@ -15,6 +15,7 @@ class Mysql2UnsignedTypeTest < ActiveRecord::Mysql2TestCase t.bigint :unsigned_bigint, unsigned: true t.float :unsigned_float, unsigned: true t.decimal :unsigned_decimal, unsigned: true, precision: 10, scale: 2 + t.column :unsigned_zerofill, "int unsigned zerofill" end end @@ -34,10 +35,10 @@ class Mysql2UnsignedTypeTest < ActiveRecord::Mysql2TestCase assert_raise(ActiveModel::RangeError) do UnsignedType.create(unsigned_bigint: -10) end - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::RangeError) do UnsignedType.create(unsigned_float: -10.0) end - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::RangeError) do UnsignedType.create(unsigned_decimal: -10.0) end end @@ -50,7 +51,7 @@ class Mysql2UnsignedTypeTest < ActiveRecord::Mysql2TestCase t.unsigned_decimal :unsigned_decimal_t, precision: 10, scale: 2 end - @connection.columns("unsigned_types").select { |c| /^unsigned_/ === c.name }.each do |column| + @connection.columns("unsigned_types").select { |c| /^unsigned_/.match?(c.name) }.each do |column| assert column.unsigned? end end diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index d3c65f3d94..b787de8453 100644 --- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -39,6 +39,10 @@ class PostgresqlActiveSchemaTest < ActiveRecord::PostgreSQLTestCase expected = %(CREATE INDEX CONCURRENTLY "index_people_on_last_name" ON "people" ("last_name")) assert_equal expected, add_index(:people, :last_name, algorithm: :concurrently) + expected = %(CREATE INDEX "index_people_on_last_name_and_first_name" ON "people" ("last_name" DESC, "first_name" ASC)) + assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: :desc, first_name: :asc }) + assert_equal expected, add_index(:people, ["last_name", :first_name], order: { last_name: :desc, "first_name" => :asc }) + %w(gin gist hash btree).each do |type| expected = %(CREATE INDEX "index_people_on_last_name" ON "people" USING #{type} ("last_name")) assert_equal expected, add_index(:people, :last_name, using: type) diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index 97960b6c51..680dad9706 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -117,15 +117,15 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase def test_select_with_strings @connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')" x = PgArray.first - assert_equal(["1","2","3"], x.tags) + assert_equal(["1", "2", "3"], x.tags) end def test_rewrite_with_strings @connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')" x = PgArray.first - x.tags = ["1","2","3","4"] + x.tags = ["1", "2", "3", "4"] x.save! - assert_equal ["1","2","3","4"], x.reload.tags + assert_equal ["1", "2", "3", "4"], x.reload.tags end def test_select_with_integers @@ -163,28 +163,28 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase end def test_strings_with_quotes - assert_cycle(:tags, ["this has",'some "s that need to be escaped"']) + assert_cycle(:tags, ["this has", 'some "s that need to be escaped"']) end def test_strings_with_commas - assert_cycle(:tags, ["this,has","many,values"]) + assert_cycle(:tags, ["this,has", "many,values"]) end def test_strings_with_array_delimiters - assert_cycle(:tags, ["{","}"]) + assert_cycle(:tags, ["{", "}"]) end def test_strings_with_null_strings - assert_cycle(:tags, ["NULL","NULL"]) + assert_cycle(:tags, ["NULL", "NULL"]) end def test_contains_nils - assert_cycle(:tags, ["1",nil,nil]) + assert_cycle(:tags, ["1", nil, nil]) end def test_insert_fixture tag_values = ["val1", "val2", "val3_with_'_multiple_quote_'_chars"] - @connection.insert_fixture({ "tags" => tag_values }, "pg_arrays" ) + @connection.insert_fixture({ "tags" => tag_values }, "pg_arrays") assert_equal(PgArray.last.tags, tag_values) end @@ -312,9 +312,9 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase end def test_encoding_arrays_of_utf8_strings - string_with_utf8 = "nový" - assert_equal [string_with_utf8], @type.deserialize(@type.serialize([string_with_utf8])) - assert_equal [[string_with_utf8]], @type.deserialize(@type.serialize([[string_with_utf8]])) + arrays_of_utf8_strings = %w(nový ファイル) + assert_equal arrays_of_utf8_strings, @type.deserialize(@type.serialize(arrays_of_utf8_strings)) + assert_equal [arrays_of_utf8_strings], @type.deserialize(@type.serialize([arrays_of_utf8_strings])) end private diff --git a/activerecord/test/cases/adapters/postgresql/bytea_test.rb b/activerecord/test/cases/adapters/postgresql/bytea_test.rb index dc0df8715a..5c207116c4 100644 --- a/activerecord/test/cases/adapters/postgresql/bytea_test.rb +++ b/activerecord/test/cases/adapters/postgresql/bytea_test.rb @@ -52,7 +52,7 @@ class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase end def test_type_case_nil - assert_equal(nil, @type.deserialize(nil)) + assert_nil(@type.deserialize(nil)) end def test_read_value @@ -66,7 +66,7 @@ class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase def test_read_nil_value @connection.execute "insert into bytea_data_type (payload) VALUES (null)" record = ByteaDataType.first - assert_equal(nil, record.payload) + assert_nil(record.payload) record.delete end @@ -106,8 +106,8 @@ class PostgresqlByteaTest < ActiveRecord::PostgreSQLTestCase def test_write_nil record = ByteaDataType.create(payload: nil) assert_not record.new_record? - assert_equal(nil, record.payload) - assert_equal(nil, ByteaDataType.where(id: record.id).first.payload) + assert_nil(record.payload) + assert_nil(ByteaDataType.where(id: record.id).first.payload) end class Serializer diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 48c82cb7b9..45aa748ffc 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -245,7 +245,7 @@ module ActiveRecord end end - protected + private def with_warning_suppression log_level = @connection.client_min_messages diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index a65d4d1ad9..c1f3a4ae2c 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -96,7 +96,7 @@ class PostgresqlPointTest < ActiveRecord::PostgreSQLTestCase assert_nothing_raised { PostgresqlPoint.new(x: "") } p = PostgresqlPoint.new(x: "") - assert_equal nil, p.x + assert_nil p.x end def test_array_of_points_round_trip diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 9236a67b11..1f35300739 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -10,6 +10,12 @@ if ActiveRecord::Base.connection.supports_extensions? store_accessor :settings, :language, :timezone end + class FakeParameters + def to_unsafe_h + { "hi" => "hi" } + end + end + def setup @connection = ActiveRecord::Base.connection @@ -64,8 +70,8 @@ if ActiveRecord::Base.connection.supports_extensions? @connection.add_column "hstores", "permissions", :hstore, default: '"users"=>"read", "articles"=>"write"' Hstore.reset_column_information - assert_equal({ "users"=>"read", "articles"=>"write" }, Hstore.column_defaults["permissions"]) - assert_equal({ "users"=>"read", "articles"=>"write" }, Hstore.new.permissions) + assert_equal({ "users" => "read", "articles" => "write" }, Hstore.column_defaults["permissions"]) + assert_equal({ "users" => "read", "articles" => "write" }, Hstore.new.permissions) ensure Hstore.reset_column_information end @@ -113,8 +119,8 @@ if ActiveRecord::Base.connection.supports_extensions? def test_type_cast_hstore assert_equal({ "1" => "2" }, @type.deserialize("\"1\"=>\"2\"")) assert_equal({}, @type.deserialize("")) - assert_equal({ "key"=>nil }, @type.deserialize("key => NULL")) - assert_equal({ "c"=>"}",'"a"'=>'b "a b' }, @type.deserialize(%q(c=>"}", "\"a\""=>"b \"a b"))) + assert_equal({ "key" => nil }, @type.deserialize("key => NULL")) + assert_equal({ "c" => "}", '"a"' => 'b "a b' }, @type.deserialize(%q(c=>"}", "\"a\""=>"b \"a b"))) end def test_with_store_accessors @@ -166,23 +172,23 @@ if ActiveRecord::Base.connection.supports_extensions? end def test_gen1 - assert_equal('" "=>""', @type.serialize(" "=>"")) + assert_equal('" "=>""', @type.serialize(" " => "")) end def test_gen2 - assert_equal('","=>""', @type.serialize(","=>"")) + assert_equal('","=>""', @type.serialize("," => "")) end def test_gen3 - assert_equal('"="=>""', @type.serialize("="=>"")) + assert_equal('"="=>""', @type.serialize("=" => "")) end def test_gen4 - assert_equal('">"=>""', @type.serialize(">"=>"")) + assert_equal('">"=>""', @type.serialize(">" => "")) end def test_parse1 - assert_equal({ "a"=>nil,"b"=>nil,"c"=>"NuLl","null"=>"c" }, @type.deserialize('a=>null,b=>NuLl,c=>"NuLl",null=>c')) + assert_equal({ "a" => nil, "b" => nil, "c" => "NuLl", "null" => "c" }, @type.deserialize('a=>null,b=>NuLl,c=>"NuLl",null=>c')) end def test_parse2 @@ -194,19 +200,19 @@ if ActiveRecord::Base.connection.supports_extensions? end def test_parse4 - assert_equal({ "=a"=>"q=w" }, @type.deserialize('\=a=>q=w')) + assert_equal({ "=a" => "q=w" }, @type.deserialize('\=a=>q=w')) end def test_parse5 - assert_equal({ "=a"=>"q=w" }, @type.deserialize('"=a"=>q\=w')) + assert_equal({ "=a" => "q=w" }, @type.deserialize('"=a"=>q\=w')) end def test_parse6 - assert_equal({ "\"a"=>"q>w" }, @type.deserialize('"\"a"=>q>w')) + assert_equal({ "\"a" => "q>w" }, @type.deserialize('"\"a"=>q>w')) end def test_parse7 - assert_equal({ "\"a"=>"q\"w" }, @type.deserialize('\"a=>q"w')) + assert_equal({ "\"a" => "q\"w" }, @type.deserialize('\"a=>q"w')) end def test_rewrite @@ -321,6 +327,10 @@ if ActiveRecord::Base.connection.supports_extensions? assert_match %r[t\.hstore "tags",\s+default: {}], output end + def test_supports_to_unsafe_h_values + assert_equal("\"hi\"=>\"hi\"", @type.serialize(FakeParameters.new)) + end + private def assert_array_cycle(array) # test creation diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb index 273b2c1c7b..93558ac4d2 100644 --- a/activerecord/test/cases/adapters/postgresql/json_test.rb +++ b/activerecord/test/cases/adapters/postgresql/json_test.rb @@ -41,8 +41,8 @@ module PostgresqlJSONSharedTestCases @connection.add_column "json_data_type", "permissions", column_type, default: { "users": "read", "posts": ["read", "write"] } JsonDataType.reset_column_information - assert_equal({ "users"=>"read", "posts"=>["read", "write"] }, JsonDataType.column_defaults["permissions"]) - assert_equal({ "users"=>"read", "posts"=>["read", "write"] }, JsonDataType.new.permissions) + assert_equal({ "users" => "read", "posts" => ["read", "write"] }, JsonDataType.column_defaults["permissions"]) + assert_equal({ "users" => "read", "posts" => ["read", "write"] }, JsonDataType.new.permissions) ensure JsonDataType.reset_column_information end @@ -84,8 +84,8 @@ module PostgresqlJSONSharedTestCases assert_equal({ "a_key" => "a_value" }, type.deserialize(data)) assert_equal({}, type.deserialize("{}")) - assert_equal({ "key"=>nil }, type.deserialize('{"key": null}')) - assert_equal({ "c"=>"}",'"a"'=>'b "a b' }, type.deserialize(%q({"c":"}", "\"a\"":"b \"a b"}))) + assert_equal({ "key" => nil }, type.deserialize('{"key": null}')) + assert_equal({ "c" => "}", '"a"' => 'b "a b' }, type.deserialize(%q({"c":"}", "\"a\"":"b \"a b"}))) end def test_rewrite @@ -104,28 +104,28 @@ module PostgresqlJSONSharedTestCases def test_select_multikey @connection.execute %q|insert into json_data_type (payload) VALUES ('{"k1":"v1", "k2":"v2", "k3":[1,2,3]}')| x = JsonDataType.first - assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1,2,3] }, x.payload) + assert_equal({ "k1" => "v1", "k2" => "v2", "k3" => [1, 2, 3] }, x.payload) end def test_null_json @connection.execute "insert into json_data_type (payload) VALUES(null)" x = JsonDataType.first - assert_equal(nil, x.payload) + assert_nil(x.payload) end def test_select_nil_json_after_create json = JsonDataType.create(payload: nil) - x = JsonDataType.where(payload:nil).first + x = JsonDataType.where(payload: nil).first assert_equal(json, x) end def test_select_nil_json_after_update json = JsonDataType.create(payload: "foo") - x = JsonDataType.where(payload:nil).first - assert_equal(nil, x) + x = JsonDataType.where(payload: nil).first + assert_nil(x) json.update_attributes payload: nil - x = JsonDataType.where(payload:nil).first + x = JsonDataType.where(payload: nil).first assert_equal(json.reload, x) end diff --git a/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb b/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb new file mode 100644 index 0000000000..082fe95053 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb @@ -0,0 +1,54 @@ +require "cases/helper" + +class PostgresqlLegacyMigrationTest < ActiveRecord::PostgreSQLTestCase + class GenerateTableWithoutBigserial < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigserial.new(nil, 1)] + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + + super + end + + def test_create_table_uses_serial_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "integer", sql_type_for(col) + assert col.serial? + end + + def test_create_tables_respects_pk_column_type_override + col = column(:override_pk, :id) + assert_equal "bigint", sql_type_for(col) + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection. + columns(table_name.to_s). + detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end +end diff --git a/activerecord/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb b/activerecord/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb new file mode 100644 index 0000000000..8c62690866 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb @@ -0,0 +1,25 @@ +require "cases/helper" +require "models/computer" +require "models/developer" + +class PreparedStatementsDisabledTest < ActiveRecord::PostgreSQLTestCase + fixtures :developers + + def setup + @conn = ActiveRecord::Base.establish_connection :arunit_without_prepared_statements + end + + def teardown + @conn.release_connection + ActiveRecord::Base.establish_connection :arunit + end + + def test_select_query_works_even_when_prepared_statements_are_disabled + assert_not Developer.connection.prepared_statements + + david = developers(:david) + + assert_equal david, Developer.where(name: "David").last # With Binds + assert_operator Developer.count, :>, 0 # Without Binds + end +end diff --git a/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb b/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb deleted file mode 100644 index b898929f8a..0000000000 --- a/activerecord/test/cases/adapters/postgresql/prepared_statements_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -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/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index 865a3a5098..141baffa5b 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -18,12 +18,12 @@ module ActiveRecord end def test_quote_float_nan - nan = 0.0/0 + nan = 0.0 / 0 assert_equal "'NaN'", @conn.quote(nan) end def test_quote_float_infinity - infinity = 1.0/0 + infinity = 1.0 / 0 assert_equal "'Infinity'", @conn.quote(infinity) end @@ -36,7 +36,7 @@ module ActiveRecord def test_quote_bit_string value = "'); SELECT * FROM users; /*\n01\n*/--" type = OID::Bit.new - assert_equal nil, @conn.quote(type.serialize(value)) + assert_nil @conn.quote(type.serialize(value)) end end end diff --git a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb index 7193f23880..f6a07da85f 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -110,7 +110,7 @@ class SchemaAuthorizationTest < ActiveRecord::PostgreSQLTestCase private def set_session_auth(auth = nil) - @connection.session_auth = auth || "default" + @connection.session_auth = auth || "default" end def bind_param(value) diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 51a2306c59..237e9ff6a5 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -383,7 +383,7 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase pk, seq = @connection.pk_and_sequence_for(given) assert_equal "id", pk, "primary key should be found when table referenced as #{given}" assert_equal pg_name.new(SCHEMA_NAME, "#{PK_TABLE_NAME}_id_seq"), seq, "sequence name should be found when table referenced as #{given}" if given == %("#{SCHEMA_NAME}"."#{PK_TABLE_NAME}") - assert_equal pg_name.new(SCHEMA_NAME, UNMATCHED_SEQUENCE_NAME), seq, "sequence name should be found when table referenced as #{given}" if given == %("#{SCHEMA_NAME}"."#{UNMATCHED_PK_TABLE_NAME}") + assert_equal pg_name.new(SCHEMA_NAME, UNMATCHED_SEQUENCE_NAME), seq, "sequence name should be found when table referenced as #{given}" if given == %("#{SCHEMA_NAME}"."#{UNMATCHED_PK_TABLE_NAME}") end end @@ -393,7 +393,7 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase SCHEMA_NAME => SCHEMA_NAME, %(#{SCHEMA2_NAME},#{SCHEMA_NAME},public) => SCHEMA2_NAME, %(public,#{SCHEMA2_NAME},#{SCHEMA_NAME}) => "public" - }.each do |given,expect| + }.each do |given, expect| with_schema_search_path(given) { assert_equal expect, @connection.current_schema } end end @@ -418,7 +418,7 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase SCHEMA_NAME => true, SCHEMA2_NAME => true, "darkside" => false - }.each do |given,expect| + }.each do |given, expect| assert_equal expect, @connection.schema_exists?(given) end end diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index e7c1d97d16..962450aada 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -21,7 +21,7 @@ class PostgresqlTimestampTest < ActiveRecord::PostgreSQLTestCase @connection.reconnect! timestamp = PostgresqlTimestampWithZone.find(1) - assert_equal Time.utc(2010,1,1, 11,0,0), timestamp.time + assert_equal Time.utc(2010, 1, 1, 11, 0, 0), timestamp.time assert_instance_of Time, timestamp.time end ensure @@ -35,7 +35,7 @@ class PostgresqlTimestampTest < ActiveRecord::PostgreSQLTestCase @connection.execute("SET time zone 'America/Jamaica'", "SCHEMA") timestamp = PostgresqlTimestampWithZone.find(1) - assert_equal Time.utc(2010,1,1, 11,0,0), timestamp.time + assert_equal Time.utc(2010, 1, 1, 11, 0, 0), timestamp.time assert_instance_of Time, timestamp.time end ensure diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb index c450524de8..9b42d0383d 100644 --- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb +++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb @@ -11,6 +11,8 @@ module ActiveRecord end setup do + @abort, Thread.abort_on_exception = Thread.abort_on_exception, false + @connection = ActiveRecord::Base.connection @connection.transaction do @@ -25,6 +27,8 @@ module ActiveRecord teardown do @connection.drop_table "samples", if_exists: true + + Thread.abort_on_exception = @abort end test "raises SerializationFailure when a serialization failure occurs" do @@ -85,7 +89,7 @@ module ActiveRecord end end - protected + private def with_warning_suppression log_level = ActiveRecord::Base.connection.client_min_messages diff --git a/activerecord/test/cases/adapters/postgresql/utils_test.rb b/activerecord/test/cases/adapters/postgresql/utils_test.rb index 01c597beae..9f9e3bda2f 100644 --- a/activerecord/test/cases/adapters/postgresql/utils_test.rb +++ b/activerecord/test/cases/adapters/postgresql/utils_test.rb @@ -7,13 +7,13 @@ class PostgreSQLUtilsTest < ActiveRecord::PostgreSQLTestCase def test_extract_schema_qualified_name { - %(table_name) => [nil,"table_name"], - %("table.name") => [nil,"table.name"], + %(table_name) => [nil, "table_name"], + %("table.name") => [nil, "table.name"], %(schema.table_name) => %w{schema table_name}, %("schema".table_name) => %w{schema table_name}, %(schema."table_name") => %w{schema table_name}, %("schema"."table_name") => %w{schema table_name}, - %("even spaces".table) => ["even spaces","table"], + %("even spaces".table) => ["even spaces", "table"], %(schema."table.name") => ["schema", "table.name"] }.each do |given, expect| assert_equal Name.new(*expect), extract_schema_qualified_name(given) @@ -56,7 +56,7 @@ class PostgreSQLNameTest < ActiveRecord::PostgreSQLTestCase test "can be used as hash key" do hash = { Name.new("schema", "article_seq") => "success" } assert_equal "success", hash[Name.new("schema", "article_seq")] - assert_equal nil, hash[Name.new("schema", "articles")] - assert_equal nil, hash[Name.new("public", "article_seq")] + assert_nil hash[Name.new("schema", "articles")] + assert_nil hash[Name.new("public", "article_seq")] end end diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 9a59691737..f34d50e25c 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -9,6 +9,10 @@ module PostgresqlUUIDHelper def drop_table(name) connection.drop_table name, if_exists: true end + + def uuid_function + connection.supports_pgcrypto_uuid? ? "gen_random_uuid()" : "uuid_generate_v4()" + end end class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase @@ -21,6 +25,7 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase setup do enable_extension!("uuid-ossp", connection) + enable_extension!("pgcrypto", connection) if connection.supports_pgcrypto_uuid? connection.create_table "uuid_data_type" do |t| t.uuid "guid" @@ -31,14 +36,22 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase drop_table "uuid_data_type" end + if ActiveRecord::Base.connection.supports_pgcrypto_uuid? + def test_uuid_column_default + connection.add_column :uuid_data_type, :thingy, :uuid, null: false, default: "gen_random_uuid()" + UUIDType.reset_column_information + column = UUIDType.columns_hash["thingy"] + assert_equal "gen_random_uuid()", column.default_function + end + end + def test_change_column_default - @connection.add_column :uuid_data_type, :thingy, :uuid, null: false, default: "uuid_generate_v1()" + connection.add_column :uuid_data_type, :thingy, :uuid, null: false, default: "uuid_generate_v1()" UUIDType.reset_column_information column = UUIDType.columns_hash["thingy"] assert_equal "uuid_generate_v1()", column.default_function - @connection.change_column :uuid_data_type, :thingy, :uuid, null: false, default: "uuid_generate_v4()" - + connection.change_column :uuid_data_type, :thingy, :uuid, null: false, default: "uuid_generate_v4()" UUIDType.reset_column_information column = UUIDType.columns_hash["thingy"] assert_equal "uuid_generate_v4()", column.default_function @@ -58,12 +71,12 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase def test_treat_blank_uuid_as_nil UUIDType.create! guid: "" - assert_equal(nil, UUIDType.last.guid) + assert_nil(UUIDType.last.guid) end def test_treat_invalid_uuid_as_nil uuid = UUIDType.create! guid: "foobar" - assert_equal(nil, uuid.guid) + assert_nil(uuid.guid) end def test_invalid_uuid_dont_modify_before_type_cast @@ -155,7 +168,7 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase # to test dumping tables which columns have defaults with custom functions connection.execute <<-SQL CREATE OR REPLACE FUNCTION my_uuid_generator() RETURNS uuid - AS $$ SELECT * FROM uuid_generate_v4() $$ + AS $$ SELECT * FROM #{uuid_function} $$ LANGUAGE SQL VOLATILE; SQL @@ -164,11 +177,16 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase t.string "name" t.uuid "other_uuid_2", default: "my_uuid_generator()" end + + connection.create_table("pg_uuids_3", id: :uuid) do |t| + t.string "name" + end end teardown do drop_table "pg_uuids" drop_table "pg_uuids_2" + drop_table "pg_uuids_3" connection.execute "DROP FUNCTION IF EXISTS my_uuid_generator();" end @@ -192,7 +210,7 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase def test_pk_and_sequence_for_uuid_primary_key pk, seq = connection.pk_and_sequence_for("pg_uuids") assert_equal "id", pk - assert_equal nil, seq + assert_nil seq end def test_schema_dumper_for_uuid_primary_key @@ -206,6 +224,36 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase 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 + + def test_schema_dumper_for_uuid_primary_key_default + schema = dump_table_schema "pg_uuids_3" + if connection.supports_pgcrypto_uuid? + assert_match(/\bcreate_table "pg_uuids_3", id: :uuid, default: -> { "gen_random_uuid\(\)" }/, schema) + else + assert_match(/\bcreate_table "pg_uuids_3", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema) + end + end + + if ActiveRecord::Base.connection.supports_pgcrypto_uuid? + def test_schema_dumper_for_uuid_primary_key_default_in_legacy_migration + @verbose_was = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migration = Class.new(ActiveRecord::Migration[4.2]) do + def version; 101 end + def migrate(x) + create_table("pg_uuids_4", id: :uuid) + end + end.new + ActiveRecord::Migrator.new(:up, [migration]).migrate + + schema = dump_table_schema "pg_uuids_4" + assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema) + ensure + drop_table "pg_uuids_4" + ActiveRecord::Migration.verbose = @verbose_was + end + end end end diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 8342b05870..91967c1e33 100644 --- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -75,7 +75,7 @@ class CopyTableTest < ActiveRecord::SQLite3TestCase test_copy_table "binaries", "binaries2" end -protected +private def copy_table(from, to, options = {}) @connection.copy_table(from, to, { temporary: true }.merge(options)) end diff --git a/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb b/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb new file mode 100644 index 0000000000..fcca8d66b5 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb @@ -0,0 +1,59 @@ +require "cases/helper" + +class SqliteLegacyMigrationTest < ActiveRecord::SQLite3TestCase + self.use_transactional_tests = false + + class GenerateTableWithoutBigint < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + @connection = ActiveRecord::Base.connection + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigint.new(nil, 1)] + + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + @connection.drop_table("legacy_integer_pk") + @connection.drop_table("override_pk") + ActiveRecord::SchemaMigration.delete_all rescue nil + super + end + + def test_create_table_uses_integer_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "INTEGER", sql_type_for(col) + assert primary_key?(:legacy_integer_pk, "id"), "id is not primary key" + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection + .columns(table_name.to_s) + .detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end + + def primary_key?(table_name, column) + ActiveRecord::Base.connection.execute("PRAGMA table_info(#{table_name})").find { |col| col["name"] == column }["pk"] == 1 + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index 80a37e83ff..9750840051 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -37,7 +37,7 @@ class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase end def test_type_cast_nil - assert_equal nil, @conn.type_cast(nil) + assert_nil @conn.type_cast(nil) end def test_type_cast_true diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 66f9349111..0526191952 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -190,7 +190,7 @@ module ActiveRecord end def test_type_cast_should_not_mutate_encoding - name = "hello".force_encoding(Encoding::ASCII_8BIT) + name = "hello".force_encoding(Encoding::ASCII_8BIT) Owner.create(name: name) assert_equal Encoding::ASCII_8BIT, name.encoding ensure diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb index e3eccad71f..397ac599b9 100644 --- a/activerecord/test/cases/ar_schema_test.rb +++ b/activerecord/test/cases/ar_schema_test.rb @@ -54,7 +54,7 @@ if ActiveRecord::Base.connection.supports_migrations? def test_schema_define_w_table_name_prefix table_name = ActiveRecord::SchemaMigration.table_name old_table_name_prefix = ActiveRecord::Base.table_name_prefix - ActiveRecord::Base.table_name_prefix = "nep_" + ActiveRecord::Base.table_name_prefix = "nep_" ActiveRecord::SchemaMigration.table_name = "nep_#{table_name}" ActiveRecord::Schema.define(version: 7) do create_table :fruits do |t| @@ -66,7 +66,7 @@ if ActiveRecord::Base.connection.supports_migrations? end assert_equal 7, ActiveRecord::Migrator::current_version ensure - ActiveRecord::Base.table_name_prefix = old_table_name_prefix + ActiveRecord::Base.table_name_prefix = old_table_name_prefix ActiveRecord::SchemaMigration.table_name = table_name end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 2418346d1b..b75e2a47a6 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -285,12 +285,22 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase end def test_failing_create! - client = Client.create!(name: "Jimmy") + client = Client.create!(name: "Jimmy") assert_raise(ActiveRecord::RecordInvalid) { client.create_account! } assert_not_nil client.account assert client.account.new_record? end + def test_reloading_the_belonging_object + odegy_account = accounts(:odegy_account) + + assert_equal "Odegy", odegy_account.firm.name + Company.where(id: odegy_account.firm_id).update_all(name: "ODEGY") + assert_equal "Odegy", odegy_account.firm.name + + assert_equal "ODEGY", odegy_account.reload_firm.name + end + def test_natural_assignment_to_nil client = Client.find(3) client.firm = nil @@ -346,7 +356,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase def test_with_select assert_equal 1, Company.find(2).firm_with_select.attributes.size - assert_equal 1, Company.all.merge!(includes: :firm_with_select ).find(2).firm_with_select.attributes.size + assert_equal 1, Company.all.merge!(includes: :firm_with_select).find(2).firm_with_select.attributes.size end def test_belongs_to_without_counter_cache_option @@ -1047,7 +1057,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase comment.parent = nil comment.save! - assert_equal nil, comment.reload.parent + assert_nil comment.reload.parent assert_equal 0, comments(:greetings).reload.children_count end @@ -1062,6 +1072,20 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal 1, parent.reload.children_count end + def test_belongs_to_with_out_of_range_value_assigning + model = Class.new(Comment) do + def self.name; "Temp"; end + validates :post, presence: true + end + + comment = model.new + comment.post_id = 9223372036854775808 # out of range in the bigint + + assert_nil comment.post + assert_not comment.valid? + assert_equal [{ error: :blank }], comment.errors.details[:post] + end + def test_polymorphic_with_custom_primary_key toy = Toy.create! sponsor = Sponsor.create!(sponsorable: toy) diff --git a/activerecord/test/cases/associations/callbacks_test.rb b/activerecord/test/cases/associations/callbacks_test.rb index 2f62d0367e..5fd2411f6f 100644 --- a/activerecord/test/cases/associations/callbacks_test.rb +++ b/activerecord/test/cases/associations/callbacks_test.rb @@ -109,7 +109,7 @@ class AssociationCallbacksTest < ActiveRecord::TestCase def self.name; Project.name; end has_and_belongs_to_many :developers_with_callbacks, class_name: "Developer", - before_add: lambda { |o,r| + before_add: lambda { |o, r| dev = r new_dev = r.new_record? } @@ -159,7 +159,7 @@ class AssociationCallbacksTest < ActiveRecord::TestCase activerecord.reload assert activerecord.developers_with_callbacks.size == 2 end - activerecord.developers_with_callbacks.flat_map { |d| ["before_removing#{d.id}","after_removing#{d.id}"] }.sort + activerecord.developers_with_callbacks.flat_map { |d| ["before_removing#{d.id}", "after_removing#{d.id}"] }.sort assert activerecord.developers_with_callbacks.clear assert_predicate activerecord.developers_log, :empty? end diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index e87431bf32..ddb5c7a4aa 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -20,7 +20,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 3, authors[1].posts.size - assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum,i| sum+i } + assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum, i| sum + i } end def test_eager_association_loading_with_cascaded_two_levels_and_one_level @@ -28,7 +28,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 3, authors[1].posts.size - assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum,i| sum+i } + assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum, i| sum + i } assert_equal 1, authors[0].categorizations.size assert_equal 2, authors[1].categorizations.size end @@ -86,7 +86,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 3, authors.size assert_equal 5, authors[0].posts.size assert_equal 3, authors[1].posts.size - assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum,i| sum+i } + assert_equal 10, authors[0].posts.collect { |post| post.comments.size }.inject(0) { |sum, i| sum + i } end def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference @@ -183,6 +183,6 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal 1, authors[1].comments.size assert_equal 5, authors[0].posts.size assert_equal 3, authors[1].posts.size - assert_equal 3, authors[0].posts.collect { |post| post.categorizations.size }.inject(0) { |sum, i| sum+i } + assert_equal 3, authors[0].posts.collect { |post| post.categorizations.size }.inject(0) { |sum, i| sum + i } end end diff --git a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb index aa82b9dd2a..4f0fe3236e 100644 --- a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb +++ b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb @@ -15,8 +15,8 @@ class EagerLoadIncludeFullStiClassNamesTest < ActiveRecord::TestCase end def generate_test_objects - post = Namespaced::Post.create( title: "Great stuff", body: "This is not", author_id: 1 ) - Tagging.create( taggable: post ) + post = Namespaced::Post.create(title: "Great stuff", body: "This is not", author_id: 1) + Tagging.create(taggable: post) end def test_class_names diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb index a7a8c6a783..e9f551b6b2 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -12,7 +12,7 @@ module Remembered included do after_create :remember - protected + private def remember; self.class.remembered << self; end end @@ -39,7 +39,7 @@ class Triangle < ActiveRecord::Base has_many :shape_expressions, as: :shape include Remembered end -class PaintColor < ActiveRecord::Base +class PaintColor < ActiveRecord::Base has_many :shape_expressions, as: :paint belongs_to :non_poly, foreign_key: "non_poly_one_id", class_name: "NonPolyOne" include Remembered diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index d1c4c1cef8..ff1bf8acd4 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -241,7 +241,7 @@ class EagerAssociationTest < ActiveRecord::TestCase post = assert_queries(1) { Post.all.merge!(includes: { author_with_address: :author_address }).find(post.id) } # find the post, then find the author which is null so no query for the author or address assert_no_queries do - assert_equal nil, post.author_with_address + assert_nil post.author_with_address end end @@ -250,7 +250,7 @@ class EagerAssociationTest < ActiveRecord::TestCase sponsor.update!(sponsorable: nil) sponsor = assert_queries(1) { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) } assert_no_queries do - assert_equal nil, sponsor.sponsorable + assert_nil sponsor.sponsorable end end @@ -261,7 +261,7 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_nothing_raised { Sponsor.all.merge!(includes: :sponsorable).find(sponsor.id) } end assert_no_queries do - assert_equal nil, sponsor.sponsorable + assert_nil sponsor.sponsorable end end @@ -356,31 +356,31 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_association_loading_with_belongs_to_and_limit comments = Comment.all.merge!(includes: :post, limit: 5, order: "comments.id").to_a assert_equal 5, comments.length - assert_equal [1,2,3,5,6], comments.collect(&:id) + assert_equal [1, 2, 3, 5, 6], comments.collect(&:id) end def test_eager_association_loading_with_belongs_to_and_limit_and_conditions comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, order: "comments.id").to_a assert_equal 3, comments.length - assert_equal [5,6,7], comments.collect(&:id) + assert_equal [5, 6, 7], comments.collect(&:id) end def test_eager_association_loading_with_belongs_to_and_limit_and_offset comments = Comment.all.merge!(includes: :post, limit: 3, offset: 2, order: "comments.id").to_a assert_equal 3, comments.length - assert_equal [3,5,6], comments.collect(&:id) + assert_equal [3, 5, 6], comments.collect(&:id) end def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions comments = Comment.all.merge!(includes: :post, where: "post_id = 4", limit: 3, offset: 1, order: "comments.id").to_a assert_equal 3, comments.length - assert_equal [6,7,8], comments.collect(&:id) + assert_equal [6, 7, 8], comments.collect(&:id) end def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array - comments = Comment.all.merge!(includes: :post, where: ["post_id = ?",4], limit: 3, offset: 1, order: "comments.id").to_a + comments = Comment.all.merge!(includes: :post, where: ["post_id = ?", 4], limit: 3, offset: 1, order: "comments.id").to_a assert_equal 3, comments.length - assert_equal [6,7,8], comments.collect(&:id) + assert_equal [6, 7, 8], comments.collect(&:id) end def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name @@ -395,14 +395,14 @@ class EagerAssociationTest < ActiveRecord::TestCase comments = Comment.all.merge!(includes: :post, where: { posts: { id: 4 } }, limit: 3, order: "comments.id").to_a end assert_equal 3, comments.length - assert_equal [5,6,7], comments.collect(&:id) + assert_equal [5, 6, 7], comments.collect(&:id) assert_no_queries do comments.first.post end end def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name - quoted_posts_id= Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id") + quoted_posts_id = Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id") assert_nothing_raised do Comment.includes(:post).references(:posts).where("#{quoted_posts_id} = ?", 4) end @@ -415,7 +415,7 @@ class EagerAssociationTest < ActiveRecord::TestCase end def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name - quoted_posts_id= Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id") + quoted_posts_id = Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id") assert_nothing_raised do Comment.includes(:post).references(:posts).order(quoted_posts_id) end @@ -452,8 +452,8 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_load_has_many_quotes_table_and_column_names michael = Person.all.merge!(includes: :references).find(people(:michael).id) - references(:michael_magician,:michael_unicyclist) - assert_no_queries { assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) } + references(:michael_magician, :michael_unicyclist) + assert_no_queries { assert_equal references(:michael_magician, :michael_unicyclist), michael.references.sort_by(&:id) } end def test_eager_load_has_many_through_quotes_table_and_column_names @@ -464,7 +464,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_load_has_many_with_string_keys subscriptions = subscriptions(:webster_awdr, :webster_rfr) - subscriber =Subscriber.all.merge!(includes: :subscriptions).find(subscribers(:second).id) + subscriber = Subscriber.all.merge!(includes: :subscriptions).find(subscribers(:second).id) assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id) end @@ -563,13 +563,13 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_with_has_many_and_limit_and_conditions posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: "posts.body = 'hello'", order: "posts.id").to_a assert_equal 2, posts.size - assert_equal [4,5], posts.collect(&:id) + assert_equal [4, 5], posts.collect(&:id) end def test_eager_with_has_many_and_limit_and_conditions_array posts = Post.all.merge!(includes: [ :author, :comments ], limit: 2, where: [ "posts.body = ?", "hello" ], order: "posts.id").to_a assert_equal 2, posts.size - assert_equal [4,5], posts.collect(&:id) + assert_equal [4, 5], posts.collect(&:id) end def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers @@ -740,7 +740,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_with_invalid_association_reference assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { - Post.all.merge!(includes: :monkeys ).find(6) + Post.all.merge!(includes: :monkeys).find(6) } assert_raise(ActiveRecord::AssociationNotFoundError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { Post.all.merge!(includes: [ :monkeys ]).find(6) @@ -844,7 +844,7 @@ class EagerAssociationTest < ActiveRecord::TestCase end end - def find_all_ordered(className, include=nil) + def find_all_ordered(className, include = nil) className.all.merge!(order: "#{className.table_name}.#{className.primary_key}", includes: include).to_a end @@ -903,8 +903,8 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm # Eager includes of has many and habtm associations aren't necessarily sorted in the same way def assert_equal_after_sort(item1, item2, item3 = nil) - assert_equal(item1.sort { |a,b| a.id <=> b.id }, item2.sort { |a,b| a.id <=> b.id }) - assert_equal(item3.sort { |a,b| a.id <=> b.id }, item2.sort { |a,b| a.id <=> b.id }) if item3 + assert_equal(item1.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id }) + assert_equal(item3.sort { |a, b| a.id <=> b.id }, item2.sort { |a, b| a.id <=> b.id }) if item3 end # Test regular association, association with conditions, association with # STI, and association with conditions assured not to be true @@ -1163,7 +1163,7 @@ class EagerAssociationTest < ActiveRecord::TestCase expected = Firm.find(1).clients_using_primary_key.sort_by(&:name) # Oracle adapter truncates alias to 30 characters if current_adapter?(:OracleAdapter) - firm = Firm.all.merge!(includes: :clients_using_primary_key, order: "clients_using_primary_keys_companies"[0,30]+".name").find(1) + firm = Firm.all.merge!(includes: :clients_using_primary_key, order: "clients_using_primary_keys_companies"[0, 30] + ".name").find(1) else firm = Firm.all.merge!(includes: :clients_using_primary_key, order: "clients_using_primary_keys_companies.name").find(1) end @@ -1360,7 +1360,7 @@ class EagerAssociationTest < ActiveRecord::TestCase test "including associations with where.not adds implicit references" do author = assert_queries(2) { - Author.includes(:posts).where.not(posts: { title: "Welcome to the weblog" } ).last + Author.includes(:posts).where.not(posts: { title: "Welcome to the weblog" }).last } assert_no_queries { diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index cc86e1a16d..974a3080d4 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -45,7 +45,7 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase # Marshaling an association shouldn't make it unusable by wiping its reflection. assert_not_nil david.association(:projects).reflection - david_too = Marshal.load(marshalled) + david_too = Marshal.load(marshalled) assert_equal projects(:action_controller), david_too.projects.find_most_recent 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 06fc7a4388..4b7ac594cf 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 @@ -86,6 +86,10 @@ class DeveloperWithSymbolClassName < Developer has_and_belongs_to_many :projects, class_name: :ProjectWithSymbolsForKeys end +class DeveloperWithConstantClassName < Developer + has_and_belongs_to_many :projects, class_name: ProjectWithSymbolsForKeys +end + class DeveloperWithExtendOption < Developer module NamedExtension def category @@ -249,8 +253,8 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert !p.persisted? assert aredridel.save assert aredridel.persisted? - assert_equal no_of_devels+1, Developer.count - assert_equal no_of_projects+1, Project.count + assert_equal no_of_devels + 1, Developer.count + assert_equal no_of_projects + 1, Project.count assert_equal 2, aredridel.projects.size assert_equal 2, aredridel.projects.reload.size end @@ -379,7 +383,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase dev.projects << projects(:active_record) assert_equal 3, dev.projects.size - assert_equal 1, dev.projects.distinct.size + assert_equal 1, dev.projects.uniq.size end def test_distinct_before_the_fact @@ -939,7 +943,15 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase def test_with_symbol_class_name assert_nothing_raised do - DeveloperWithSymbolClassName.new + developer = DeveloperWithSymbolClassName.new + developer.projects + end + end + + def test_with_constant_class_name + assert_nothing_raised do + developer = DeveloperWithConstantClassName.new + developer.projects end end @@ -1000,4 +1012,17 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase user = User.create! assert_nothing_raised { user.jobs_pool.clear } end + + def test_has_and_belongs_to_many_while_partial_writes_false + begin + original_partial_writes = ActiveRecord::Base.partial_writes + ActiveRecord::Base.partial_writes = false + developer = Developer.new(name: "Mehmet Emin İNAÇ") + developer.projects << Project.new(name: "Bounty") + + assert developer.save + ensure + ActiveRecord::Base.partial_writes = original_partial_writes + end + 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 0ce67f971b..482b086e5c 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -84,7 +84,7 @@ class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase david = people(:david) assert_equal ["A Modest Proposal"], david.essays.map(&:name) - david.essays = [Essay.create!(name: "Remote Work" )] + david.essays = [Essay.create!(name: "Remote Work")] assert_equal ["Remote Work"], david.essays.map(&:name) end @@ -187,7 +187,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase ship.parts.clear part.reload - assert_equal nil, part.ship + assert_nil part.ship assert !part.updated_at_changed? end @@ -528,7 +528,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_should_append_to_association_order - ordered_clients = companies(:first_firm).clients_sorted_desc.order("companies.id") + ordered_clients = companies(:first_firm).clients_sorted_desc.order("companies.id") assert_equal ["id DESC", "companies.id"], ordered_clients.order_values end @@ -788,6 +788,13 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id) end + def test_select_with_block_and_specific_attributes + assert_deprecated do + comments = posts(:welcome).comments.select(:id, :body) { |c| c.id == 1 } + assert_equal [1], comments.map(&:id) + end + end + def test_select_without_foreign_key assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit end @@ -912,6 +919,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase company.clients_of_firm.build("name" => "Another Client") company.clients_of_firm.build("name" => "Yet Another Client") assert_equal 4, company.clients_of_firm.size + assert_equal 4, company.clients_of_firm.uniq.size end def test_collection_not_empty_after_building @@ -983,7 +991,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_create_without_loading_association - first_firm = companies(:first_firm) + first_firm = companies(:first_firm) Firm.column_names Client.column_names @@ -1735,6 +1743,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert !company.clients.loaded? end + def test_counter_cache_on_unloaded_association + car = Car.create(name: "My AppliCar") + assert_equal car.engines.size, 0 + end + def test_get_ids_ignores_include_option assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids end @@ -2291,7 +2304,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase test "does not duplicate associations when used with natural primary keys" do speedometer = Speedometer.create!(id: "4") - speedometer.minivans.create!(minivan_id: "a-van-red" ,name: "a van", color: "red") + speedometer.minivans.create!(minivan_id: "a-van-red" , name: "a van", color: "red") assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}" assert_equal 1, speedometer.reload.minivans.to_a.size @@ -2462,7 +2475,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase test "double insertion of new object to association when same association used in the after create callback of a new object" do reset_callbacks(:save, Bulb) do - Bulb.after_save { |record| record.car.bulbs.to_a } + Bulb.after_save { |record| record.car.bulbs.load } car = Car.create! car.bulbs << Bulb.new assert_equal 1, car.bulbs.size 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 9f716d7820..fd79d4a5f9 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -75,7 +75,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase posts = person_prime.includes(:posts).first.posts assert_operator posts.length, :>, 1 - posts.each_cons(2) do |left,right| + posts.each_cons(2) do |left, right| assert_operator left.id, :>, right.id end end @@ -402,7 +402,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end end - assert_equal nil, reference.reload.job_id + assert_nil reference.reload.job_id ensure Reference.make_comments = false end @@ -423,7 +423,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end # Check that the destroy callback on Reference did not run - assert_equal nil, person.reload.comments + assert_nil person.reload.comments ensure Reference.make_comments = false end @@ -485,7 +485,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end references.each do |reference| - assert_equal nil, reference.reload.job_id + assert_nil reference.reload.job_id end end @@ -702,7 +702,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase [:added, :after, "Bob"], [:added, :before, "Lary"], [:added, :after, "Lary"] - ],log.last(6) + ], log.last(6) post.people_with_callbacks.build(first_name: "Ted") assert_equal [ @@ -716,7 +716,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase [:added, :after, "Sam"] ], log.last(2) - post.people_with_callbacks = [people(:michael),people(:david), Person.new(first_name: "Julian"), Person.create!(first_name: "Roger")] + post.people_with_callbacks = [people(:michael), people(:david), Person.new(first_name: "Julian"), Person.create!(first_name: "Roger")] assert_equal((%w(Ted Bob Sam Lary) * 2).sort, log[-12..-5].collect(&:last).sort) assert_equal [ [:added, :before, "Julian"], @@ -883,10 +883,32 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end + def test_collection_singular_ids_setter_with_changed_primary_key + company = companies(:first_firm) + client = companies(:first_client) + company.clients_using_primary_key_ids = [client.name] + assert_equal [client], company.clients_using_primary_key + end + def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set company = companies(:rails_core) - ids = [Developer.first.id, -9999] - assert_raises(ActiveRecord::AssociationTypeMismatch) { company.developer_ids= ids } + ids = [Developer.first.id, -9999] + e = assert_raises(ActiveRecord::RecordNotFound) { company.developer_ids = ids } + assert_match(/Couldn't find all Developers with 'id'/, e.message) + end + + def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set_with_changed_primary_key + company = companies(:first_firm) + ids = [Client.first.name, "unknown client"] + e = assert_raises(ActiveRecord::RecordNotFound) { company.clients_using_primary_key_ids = ids } + assert_match(/Couldn't find all Clients with 'name'/, e.message) + end + + def test_collection_singular_ids_through_setter_raises_exception_when_invalid_ids_set + author = authors(:david) + ids = [categories(:general).name, "Unknown"] + e = assert_raises(ActiveRecord::RecordNotFound) { author.essay_category_ids = ids } + assert_equal "Couldn't find all Categories with 'name': (General, Unknown) (found 1 results, but was looking for 2)", e.message end def test_build_a_model_from_hm_through_association_with_where_clause diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 1a0e6d2f8e..48fbc5990c 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -326,6 +326,16 @@ class HasOneAssociationsTest < ActiveRecord::TestCase end end + def test_reload_association + odegy = companies(:odegy) + + assert_equal 53, odegy.account.credit_limit + Account.where(id: odegy.account.id).update_all(credit_limit: 80) + assert_equal 53, odegy.account.credit_limit + + assert_equal 80, odegy.reload_account.credit_limit + end + def test_build firm = Firm.new("name" => "GlobalMegaCorp") firm.save @@ -601,7 +611,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase new_ship = Ship.create(name: "new name") assert_queries(2) do - # One query for updating name and second query for updating pirate_id + # One query to nullify the old ship, one query to update the new ship pirate.ship = new_ship end @@ -675,6 +685,6 @@ class HasOneAssociationsTest < ActiveRecord::TestCase book = SpecialBook.create!(status: "published") author.book = book - refute_equal 0, SpecialAuthor.joins(:book).where(books: { status: "published" } ).count + refute_equal 0, SpecialAuthor.joins(:book).where(books: { status: "published" }).count end end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index b2f47d2daf..432c3526a5 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -82,7 +82,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase def test_set_record_to_nil_should_delete_association @member.club = nil @member.reload - assert_equal nil, @member.current_membership + assert_nil @member.current_membership assert_nil @member.club end @@ -110,12 +110,12 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase # conditions on the through table assert_equal clubs(:moustache_club), Member.all.merge!(includes: :favourite_club).find(@member.id).favourite_club memberships(:membership_of_favourite_club).update_columns(favourite: false) - assert_equal nil, Member.all.merge!(includes: :favourite_club).find(@member.id).reload.favourite_club + assert_nil Member.all.merge!(includes: :favourite_club).find(@member.id).reload.favourite_club # conditions on the source table assert_equal clubs(:moustache_club), Member.all.merge!(includes: :hairy_club).find(@member.id).hairy_club clubs(:moustache_club).update_columns(name: "Association of Clean-Shaven Persons") - assert_equal nil, Member.all.merge!(includes: :hairy_club).find(@member.id).reload.hairy_club + assert_nil Member.all.merge!(includes: :hairy_club).find(@member.id).reload.hairy_club end def test_has_one_through_polymorphic_with_source_type @@ -123,7 +123,7 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase end def test_eager_has_one_through_polymorphic_with_source_type - clubs = Club.all.merge!(includes: :sponsored_member, where: ["name = ?","Moustache and Eyebrow Fancier Club"]).to_a + clubs = Club.all.merge!(includes: :sponsored_member, where: ["name = ?", "Moustache and Eyebrow Fancier Club"]).to_a # Only the eyebrow fanciers club has a sponsored_member assert_not_nil assert_no_queries { clubs[0].sponsored_member } end diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 15a7ae941a..a4345f3857 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -155,21 +155,21 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase old_count = posts(:welcome).taggings.count tagging = posts(:welcome).taggings.create(tag: tags(:misc)) assert_equal "Post", tagging.taggable_type - assert_equal old_count+1, posts(:welcome).taggings.count + assert_equal old_count + 1, posts(:welcome).taggings.count end def test_create_bang_polymorphic_with_has_many_scope old_count = posts(:welcome).taggings.count tagging = posts(:welcome).taggings.create!(tag: tags(:misc)) assert_equal "Post", tagging.taggable_type - assert_equal old_count+1, posts(:welcome).taggings.count + assert_equal old_count + 1, posts(:welcome).taggings.count end def test_create_polymorphic_has_one_with_scope old_count = Tagging.count tagging = posts(:welcome).create_tagging(tag: tags(:misc)) assert_equal "Post", tagging.taggable_type - assert_equal old_count+1, Tagging.count + assert_equal old_count + 1, Tagging.count end def test_delete_polymorphic_has_many_with_delete_all @@ -179,7 +179,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase old_count = Tagging.count post.destroy - assert_equal old_count-1, Tagging.count + assert_equal old_count - 1, Tagging.count assert_equal 0, posts(:welcome).taggings.count end @@ -190,7 +190,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase old_count = Tagging.count post.destroy - assert_equal old_count-1, Tagging.count + assert_equal old_count - 1, Tagging.count assert_equal 0, posts(:welcome).taggings.count end @@ -212,7 +212,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase old_count = Tagging.count post.destroy - assert_equal old_count-1, Tagging.count + assert_equal old_count - 1, Tagging.count posts(:welcome).association(:tagging).reload assert_nil posts(:welcome).tagging end @@ -402,7 +402,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase end def test_has_many_through_polymorphic_has_one - assert_equal Tagging.find(1,2).sort_by(&:id), authors(:david).taggings_2 + assert_equal Tagging.find(1, 2).sort_by(&:id), authors(:david).taggings_2 end def test_has_many_through_polymorphic_has_many @@ -413,7 +413,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase author = Author.includes(:taggings).find authors(:david).id expected_taggings = taggings(:welcome_general, :thinking_general) assert_no_queries do - assert_equal expected_taggings, author.taggings.distinct.sort_by(&:id) + assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id) end end @@ -421,7 +421,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase author = Author.all.merge!(where: ["name = ?", "David"], includes: :comments, order: "comments.id").first SpecialComment.new; VerySpecialComment.new assert_no_queries do - assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id) + assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10, 12], author.comments.collect(&:id) end end @@ -493,25 +493,25 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase push = Tag.create!(name: "pushme") post_thinking = posts(:thinking) assert_nothing_raised { post_thinking.tags << push } - assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag }, + assert_nil(wrong = post_thinking.tags.detect { |t| t.class != Tag }, message = "Expected a Tag in tags collection, got #{wrong.class}.") - assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, + assert_nil(wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, message = "Expected a Tagging in taggings collection, got #{wrong.class}.") assert_equal(count + 1, post_thinking.reload.tags.size) assert_equal(count + 1, post_thinking.tags.reload.size) assert_kind_of Tag, post_thinking.tags.create!(name: "foo") - assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag }, + assert_nil(wrong = post_thinking.tags.detect { |t| t.class != Tag }, message = "Expected a Tag in tags collection, got #{wrong.class}.") - assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, + assert_nil(wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, message = "Expected a Tagging in taggings collection, got #{wrong.class}.") assert_equal(count + 2, post_thinking.reload.tags.size) assert_equal(count + 2, post_thinking.tags.reload.size) assert_nothing_raised { post_thinking.tags.concat(Tag.create!(name: "abc"), Tag.create!(name: "def")) } - assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag }, + assert_nil(wrong = post_thinking.tags.detect { |t| t.class != Tag }, message = "Expected a Tag in tags collection, got #{wrong.class}.") - assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, + assert_nil(wrong = post_thinking.taggings.detect { |t| t.class != Tagging }, message = "Expected a Tagging in taggings collection, got #{wrong.class}.") assert_equal(count + 4, post_thinking.reload.tags.size) assert_equal(count + 4, post_thinking.tags.reload.size) diff --git a/activerecord/test/cases/associations/left_outer_join_association_test.rb b/activerecord/test/cases/associations/left_outer_join_association_test.rb index 2cc6468827..42dbbad1c8 100644 --- a/activerecord/test/cases/associations/left_outer_join_association_test.rb +++ b/activerecord/test/cases/associations/left_outer_join_association_test.rb @@ -5,7 +5,6 @@ require "models/author" require "models/essay" require "models/categorization" require "models/person" -require "active_support/core_ext/regexp" class LeftOuterJoinAssociationTest < ActiveRecord::TestCase fixtures :authors, :essays, :posts, :comments, :categorizations, :people diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index a8592bd179..978dd93fa4 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -14,6 +14,7 @@ module ActiveRecord def self.decorate_matching_attribute_types(*); end def self.initialize_generated_modules; end + include ActiveRecord::DefineCallbacks include ActiveRecord::AttributeMethods def self.attribute_names diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 4c77ecab7c..3dc0c0ce53 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -92,7 +92,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase test "attribute keys on a new instance" do t = Topic.new - assert_equal nil, t.title, "The topics table has a title column, so it should be nil" + assert_nil t.title, "The topics table has a title column, so it should be nil" assert_raise(NoMethodError) { t.title2 } end @@ -156,7 +156,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase keyboard = Keyboard.create keyboard.key_number = "10" assert_equal "10", keyboard.id_before_type_cast - assert_equal nil, keyboard.read_attribute_before_type_cast("id") + assert_nil keyboard.read_attribute_before_type_cast("id") assert_equal "10", keyboard.read_attribute_before_type_cast("key_number") assert_equal "10", keyboard.read_attribute_before_type_cast(:key_number) end @@ -213,7 +213,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase record.written_on = "345643456" assert_equal "345643456", record.written_on_before_type_cast - assert_equal nil, record.written_on + assert_nil record.written_on record.written_on = "2009-10-11 12:13:14" assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast @@ -294,7 +294,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase topic = Topic.new(new_topic) assert_equal new_topic[:title], topic.title - topic.attributes= new_topic_values + topic.attributes = new_topic_values assert_equal new_topic_values[:title], topic.title end @@ -319,6 +319,13 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_equal "Still another topic: part 4", topic.title end + test "write_attribute can write aliased attributes as well" do + topic = Topic.new(title: "Don't change the topic") + topic.write_attribute :heading, "New topic" + + assert_equal "New topic", topic.title + end + test "read_attribute" do topic = Topic.new topic.title = "Don't change the topic" @@ -329,6 +336,16 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_equal "Don't change the topic", topic[:title] end + test "read_attribute can read aliased attributes as well" do + topic = Topic.new(title: "Don't change the topic") + + assert_equal "Don't change the topic", topic.read_attribute("heading") + assert_equal "Don't change the topic", topic["heading"] + + assert_equal "Don't change the topic", topic.read_attribute(:heading) + assert_equal "Don't change the topic", topic[:heading] + end + test "read_attribute raises ActiveModel::MissingAttributeError when the attribute does not exist" do computer = Computer.select("id").first assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] } @@ -609,7 +626,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase utc_time = Time.utc(2008, 1, 1) cst_time = utc_time.in_time_zone("Central Time (US & Canada)") in_time_zone "Pacific Time (US & Canada)" do - record = @target.new + record = @target.new record.written_on = cst_time assert_equal utc_time, record.written_on assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone @@ -633,7 +650,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase (-11..13).each do |timezone_offset| time_string = utc_time.in_time_zone(timezone_offset).to_s in_time_zone "Pacific Time (US & Canada)" do - record = @target.new + record = @target.new record.written_on = time_string assert_equal Time.zone.parse(time_string), record.written_on assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone @@ -654,7 +671,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase test "setting a time zone-aware attribute to a blank string returns nil" do in_time_zone "Pacific Time (US & Canada)" do - record = @target.new + record = @target.new record.written_on = " " assert_nil record.written_on assert_nil record[:written_on] @@ -665,7 +682,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase time_string = "Tue Jan 01 00:00:00 2008" (-11..13).each do |timezone_offset| in_time_zone timezone_offset do - record = @target.new + record = @target.new record.written_on = time_string assert_equal Time.zone.parse(time_string), record.written_on assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone @@ -677,7 +694,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase test "setting a time zone-aware datetime in the current time zone" do utc_time = Time.utc(2008, 1, 1) in_time_zone "Pacific Time (US & Canada)" do - record = @target.new + record = @target.new record.written_on = utc_time.in_time_zone assert_equal utc_time, record.written_on assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone @@ -737,7 +754,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase test "time zone-aware attributes do not recurse infinitely on invalid values" do in_time_zone "Pacific Time (US & Canada)" do record = @target.new(bonus_time: []) - assert_equal nil, record.bonus_time + assert_nil record.bonus_time end end diff --git a/activerecord/test/cases/attribute_set_test.rb b/activerecord/test/cases/attribute_set_test.rb index 059b5b2401..bd4b200735 100644 --- a/activerecord/test/cases/attribute_set_test.rb +++ b/activerecord/test/cases/attribute_set_test.rb @@ -25,7 +25,7 @@ module ActiveRecord attributes = builder.build_from_database(foo: "3.3") assert_equal "3.3", attributes[:foo].value_before_type_cast - assert_equal nil, attributes[:bar].value_before_type_cast + assert_nil attributes[:bar].value_before_type_cast assert_equal :bar, attributes[:bar].name end diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index f4620ae2da..3705a6be89 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -255,5 +255,13 @@ module ActiveRecord assert_includes inspection, "non_existent_decimal" end + + test "attributes do not require a type" do + klass = Class.new(OverloadedType) do + attribute :no_type + end + assert_equal 1, klass.new(no_type: 1).no_type + assert_equal "foo", klass.new(no_type: "foo").no_type + end end end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index c24d7b8835..eb80ae4f7c 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -36,11 +36,11 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase private - def should_be_cool - unless self.first_name == "cool" - errors.add :first_name, "not cool" + def should_be_cool + unless self.first_name == "cool" + errors.add :first_name, "not cool" + end end - end } reference = Class.new(ActiveRecord::Base) { self.table_name = "references" @@ -792,6 +792,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end @ship.pirate.catchphrase = "Changed Catchphrase" + @ship.name_will_change! assert_raise(RuntimeError) { assert !@pirate.save } assert_not_nil @pirate.reload.ship @@ -1130,7 +1131,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase assert_queries(0) { @ship.save! } @parrot = @pirate.parrots.create(name: "some_name") - @parrot.name="changed_name" + @parrot.name = "changed_name" assert_queries(1) { @ship.save! } assert_queries(0) { @ship.save! } end @@ -1698,3 +1699,27 @@ class TestAutosaveAssociationWithTouch < ActiveRecord::TestCase assert_nothing_raised { invoice.line_items.create(amount: 10) } end end + +class TestAutosaveAssociationOnAHasManyAssociationWithInverse < ActiveRecord::TestCase + class Post < ActiveRecord::Base + has_many :comments, inverse_of: :post + end + + class Comment < ActiveRecord::Base + belongs_to :post, inverse_of: :comments + + attr_accessor :post_comments_count + after_save do + self.post_comments_count = post.comments.count + end + end + + def test_after_save_callback_with_autosave + post = Post.new(title: "Test", body: "...") + comment = post.comments.build(body: "...") + post.save! + + assert_equal 1, post.comments.count + assert_equal 1, comment.post_comments_count + end +end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index fafa144c6f..ad9bc60944 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -494,12 +494,12 @@ class BasicsTest < ActiveRecord::TestCase def test_utc_as_time_zone_and_new with_timezone_config default: :utc do - attributes = { "bonus_time(1i)"=>"2000", - "bonus_time(2i)"=>"1", - "bonus_time(3i)"=>"1", - "bonus_time(4i)"=>"10", - "bonus_time(5i)"=>"35", - "bonus_time(6i)"=>"50" } + attributes = { "bonus_time(1i)" => "2000", + "bonus_time(2i)" => "1", + "bonus_time(3i)" => "1", + "bonus_time(4i)" => "10", + "bonus_time(5i)" => "35", + "bonus_time(6i)" => "50" } topic = Topic.new(attributes) assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time end @@ -622,7 +622,7 @@ class BasicsTest < ActiveRecord::TestCase Topic.find(topic.id).destroy end - assert_equal nil, Topic.find_by_id(topic.id) + assert_nil Topic.find_by_id(topic.id) end def test_comparison_with_different_objects @@ -898,7 +898,7 @@ class BasicsTest < ActiveRecord::TestCase # fixed dates / times assert_equal Date.new(2004, 1, 1), default.fixed_date - assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time + assert_equal Time.local(2004, 1, 1, 0, 0, 0, 0), default.fixed_time # char types assert_equal "Y", default.char1 @@ -1109,7 +1109,7 @@ class BasicsTest < ActiveRecord::TestCase end def test_set_table_name_with_inheritance - k = Class.new( ActiveRecord::Base ) + k = Class.new(ActiveRecord::Base) def k.name; "Foo"; end def k.table_name; super + "ks"; end assert_equal "foosks", k.table_name @@ -1160,7 +1160,7 @@ class BasicsTest < ActiveRecord::TestCase end def test_find_last - last = Developer.last + last = Developer.last assert_equal last, Developer.all.merge!(order: "id desc").first end @@ -1179,17 +1179,17 @@ class BasicsTest < ActiveRecord::TestCase end def test_find_ordered_last - last = Developer.all.merge!(order: "developers.salary ASC").last + last = Developer.all.merge!(order: "developers.salary ASC").last assert_equal last, Developer.all.merge!(order: "developers.salary ASC").to_a.last end def test_find_reverse_ordered_last - last = Developer.all.merge!(order: "developers.salary DESC").last + last = Developer.all.merge!(order: "developers.salary DESC").last assert_equal last, Developer.all.merge!(order: "developers.salary DESC").to_a.last end def test_find_multiple_ordered_last - last = Developer.all.merge!(order: "developers.name, developers.salary DESC").last + last = Developer.all.merge!(order: "developers.name, developers.salary DESC").last assert_equal last, Developer.all.merge!(order: "developers.name, developers.salary DESC").to_a.last end @@ -1204,7 +1204,7 @@ class BasicsTest < ActiveRecord::TestCase end def test_find_symbol_ordered_last - last = Developer.all.merge!(order: :salary).last + last = Developer.all.merge!(order: :salary).last assert_equal last, Developer.all.merge!(order: :salary).to_a.last end @@ -1284,7 +1284,7 @@ class BasicsTest < ActiveRecord::TestCase def test_marshal_round_trip expected = posts(:welcome) marshalled = Marshal.dump(expected) - actual = Marshal.load(marshalled) + actual = Marshal.load(marshalled) assert_equal expected.attributes, actual.attributes end @@ -1428,6 +1428,16 @@ class BasicsTest < ActiveRecord::TestCase assert_nil hash["firm_name"] end + def test_slice_accepts_array_argument + attrs = { + title: "slice", + author_name: "@Cohen-Carlisle", + content: "accept arrays so I don't have to splat" + }.with_indifferent_access + topic = Topic.new(attrs) + assert_equal attrs, topic.slice(attrs.keys) + end + def test_default_values_are_deeply_dupped company = Company.new company.description << "foo" diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index db2871d383..87e99fb25c 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -92,14 +92,14 @@ class CalculationsTest < ActiveRecord::TestCase def test_should_group_by_field c = Account.group(:firm_id).sum(:credit_limit) - [1,6,2].each do |firm_id| + [1, 6, 2].each do |firm_id| assert_includes c.keys, firm_id, "Group #{c.inspect} does not contain firm_id #{firm_id}" end end def test_should_group_by_arel_attribute c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit) - [1,6,2].each do |firm_id| + [1, 6, 2].each do |firm_id| assert_includes c.keys, firm_id, "Group #{c.inspect} does not contain firm_id #{firm_id}" end end @@ -453,7 +453,7 @@ class CalculationsTest < ActiveRecord::TestCase def test_should_count_field_in_joined_table_with_group_by c = Account.group("accounts.firm_id").joins(:firm).count("companies.id") - [1,6,2,9].each { |firm_id| assert_includes c.keys, firm_id } + [1, 6, 2, 9].each { |firm_id| assert_includes c.keys, firm_id } end def test_should_count_field_of_root_table_with_conflicting_group_by_column @@ -572,7 +572,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_pluck - assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id) + assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck(:id) end def test_pluck_without_column_names @@ -608,7 +608,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_pluck_with_qualified_column_name - assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id") + assert_equal [1, 2, 3, 4, 5], Topic.order(:id).pluck("topics.id") end def test_pluck_auto_table_name_prefix @@ -688,7 +688,7 @@ class CalculationsTest < ActiveRecord::TestCase def test_pluck_replaces_select_clause taks_relation = Topic.select(:approved, :id).order(:id) - assert_equal [1,2,3,4,5], taks_relation.pluck(:id) + assert_equal [1, 2, 3, 4, 5], taks_relation.pluck(:id) assert_equal [false, true, true, true, true], taks_relation.pluck(:approved) end diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 4b517e9d70..11ec6fb2c5 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -449,7 +449,7 @@ class CallbacksTest < ActiveRecord::TestCase assert david.valid? assert !david.save exc = assert_raise(ActiveRecord::RecordNotSaved) { david.save! } - assert_equal exc.record, david + assert_equal david, exc.record assert_equal "Failed to save the record", exc.message end @@ -493,7 +493,7 @@ class CallbacksTest < ActiveRecord::TestCase assert_deprecated do assert !david.destroy exc = assert_raise(ActiveRecord::RecordNotDestroyed) { david.destroy! } - assert_equal exc.record, david + assert_equal david, exc.record assert_equal "Failed to destroy the record", exc.message end assert_not_nil ImmutableDeveloper.find_by_id(1) @@ -527,7 +527,7 @@ class CallbacksTest < ActiveRecord::TestCase assert david.valid? assert !david.save exc = assert_raise(ActiveRecord::RecordNotSaved) { david.save! } - assert_equal exc.record, david + assert_equal david, exc.record david = DeveloperWithCanceledCallbacks.find(1) david.salary = 10_000_000 @@ -554,7 +554,7 @@ class CallbacksTest < ActiveRecord::TestCase david = DeveloperWithCanceledCallbacks.find(1) assert !david.destroy exc = assert_raise(ActiveRecord::RecordNotDestroyed) { david.destroy! } - assert_equal exc.record, david + assert_equal david, exc.record assert_not_nil ImmutableDeveloper.find_by_id(1) someone = CallbackHaltedDeveloper.find(1) diff --git a/activerecord/test/cases/collection_cache_key_test.rb b/activerecord/test/cases/collection_cache_key_test.rb index a2874438c1..381a78a8e2 100644 --- a/activerecord/test/cases/collection_cache_key_test.rb +++ b/activerecord/test/cases/collection_cache_key_test.rb @@ -28,20 +28,20 @@ module ActiveRecord end test "it triggers at most one query" do - developers = Developer.where(name: "David") + developers = Developer.where(name: "David") assert_queries(1) { developers.cache_key } assert_queries(0) { developers.cache_key } end test "it doesn't trigger any query if the relation is already loaded" do - developers = Developer.where(name: "David").load + developers = Developer.where(name: "David").load assert_queries(0) { developers.cache_key } end test "relation cache_key changes when the sql query changes" do developers = Developer.where(name: "David") - other_relation = Developer.where(name: "David").where("1 = 1") + other_relation = Developer.where(name: "David").where("1 = 1") assert_not_equal developers.cache_key, other_relation.cache_key end diff --git a/activerecord/test/cases/comment_test.rb b/activerecord/test/cases/comment_test.rb index 262ad319be..a625299e8d 100644 --- a/activerecord/test/cases/comment_test.rb +++ b/activerecord/test/cases/comment_test.rb @@ -2,7 +2,6 @@ require "cases/helper" require "support/schema_dumping_helper" if ActiveRecord::Base.connection.supports_comments? - class CommentTest < ActiveRecord::TestCase include SchemaDumpingHelper @@ -102,6 +101,7 @@ if ActiveRecord::Base.connection.supports_comments? # Do all the stuff from other tests @connection.add_column :commenteds, :rating, :integer, comment: "I am running out of imagination" @connection.change_column :commenteds, :content, :string, comment: "Whoa, content describes itself!" + @connection.change_column :commenteds, :content, :string @connection.change_column :commenteds, :obvious, :string, comment: nil @connection.add_index :commenteds, :obvious, name: "idx_obvious", comment: "We need to see obvious comments" @@ -135,5 +135,4 @@ if ActiveRecord::Base.connection.supports_comments? assert_no_match %r[t\.string\s+"absent_comment", comment:\n], output end end - end diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index d5d16e7568..2c33bf22ab 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -6,7 +6,7 @@ module ActiveRecord def setup @handler = ConnectionHandler.new @spec_name = "primary" - @pool = @handler.establish_connection(ActiveRecord::Base.configurations["arunit"]) + @pool = @handler.establish_connection(ActiveRecord::Base.configurations["arunit"]) end def test_establish_connection_uses_spec_name diff --git a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb index 4bb5c4f2e2..8faa67255d 100644 --- a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +++ b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb @@ -27,7 +27,7 @@ module ActiveRecord ENV["DATABASE_URL"] = "postgres://localhost/foo" config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } actual = resolve_spec(:default_env, config) - expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost", "name"=>"default_env" } + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "default_env" } assert_equal expected, actual end @@ -37,7 +37,7 @@ module ActiveRecord config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } actual = resolve_spec(:foo, config) - expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost","name"=>"foo" } + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" } assert_equal expected, actual end @@ -47,7 +47,7 @@ module ActiveRecord config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } actual = resolve_spec(:foo, config) - expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost","name"=>"foo" } + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost", "name" => "foo" } assert_equal expected, actual end @@ -55,13 +55,13 @@ module ActiveRecord ENV["DATABASE_URL"] = "postgres://localhost/foo" config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } } actual = resolve_spec(:production, config) - expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost", "name"=>"production" } + expected = { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost", "name" => "production" } assert_equal expected, actual end def test_resolver_with_database_uri_and_unknown_symbol_key ENV["DATABASE_URL"] = "postgres://localhost/foo" - config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } + config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } } assert_raises AdapterNotSpecified do resolve_spec(:production, config) end @@ -71,7 +71,7 @@ module ActiveRecord ENV["DATABASE_URL"] = "not-postgres://not-localhost/not_foo" config = { "production" => { "adapter" => "also_not_postgres", "database" => "also_not_foo" } } actual = resolve_spec("postgres://localhost/foo", config) - expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" } + expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" } assert_equal expected, actual end @@ -85,7 +85,7 @@ module ActiveRecord ENV["DATABASE_URL"] = "postgres://localhost/foo" config = { "not_default_env" => { "adapter" => "not_postgres", "database" => "not_foo" } } actual = resolve_config(config) - expect_prod = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" } + expect_prod = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" } assert_equal expect_prod, actual["default_env"] end @@ -93,7 +93,7 @@ module ActiveRecord ENV["DATABASE_URL"] = "ibm-db://localhost/foo" config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } } actual = resolve_spec(:default_env, config) - expected = { "adapter"=>"ibm_db", "database"=>"foo", "host"=>"localhost", "name"=>"default_env" } + expected = { "adapter" => "ibm_db", "database" => "foo", "host" => "localhost", "name" => "default_env" } assert_equal expected, actual end @@ -142,13 +142,13 @@ module ActiveRecord "database" => "foo", "host" => "localhost" } assert_equal expected, actual["default_env"] - assert_equal nil, actual["production"] - assert_equal nil, actual["development"] - assert_equal nil, actual["test"] - assert_equal nil, actual[:default_env] - assert_equal nil, actual[:production] - assert_equal nil, actual[:development] - assert_equal nil, actual[:test] + assert_nil actual["production"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] end def test_blank_with_database_url_with_rails_env @@ -162,15 +162,15 @@ module ActiveRecord "host" => "localhost" } assert_equal expected, actual["not_production"] - assert_equal nil, actual["production"] - assert_equal nil, actual["default_env"] - assert_equal nil, actual["development"] - assert_equal nil, actual["test"] - assert_equal nil, actual[:default_env] - assert_equal nil, actual[:not_production] - assert_equal nil, actual[:production] - assert_equal nil, actual[:development] - assert_equal nil, actual[:test] + assert_nil actual["production"] + assert_nil actual["default_env"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:not_production] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] end def test_blank_with_database_url_with_rack_env @@ -184,15 +184,15 @@ module ActiveRecord "host" => "localhost" } assert_equal expected, actual["not_production"] - assert_equal nil, actual["production"] - assert_equal nil, actual["default_env"] - assert_equal nil, actual["development"] - assert_equal nil, actual["test"] - assert_equal nil, actual[:default_env] - assert_equal nil, actual[:not_production] - assert_equal nil, actual[:production] - assert_equal nil, actual[:development] - assert_equal nil, actual[:test] + assert_nil actual["production"] + assert_nil actual["default_env"] + assert_nil actual["development"] + assert_nil actual["test"] + assert_nil actual[:default_env] + assert_nil actual[:not_production] + assert_nil actual[:production] + assert_nil actual[:development] + assert_nil actual[:test] end def test_database_url_with_ipv6_host_and_port @@ -213,7 +213,7 @@ module ActiveRecord config = { "default_env" => { "url" => "postgres://localhost/foo" } } actual = resolve_config(config) expected = { "default_env" => - { "adapter" => "postgresql", + { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" } diff --git a/activerecord/test/cases/connection_adapters/quoting_test.rb b/activerecord/test/cases/connection_adapters/quoting_test.rb deleted file mode 100644 index 59dcb96ebc..0000000000 --- a/activerecord/test/cases/connection_adapters/quoting_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "cases/helper" - -module ActiveRecord - module ConnectionAdapters - module Quoting - class QuotingTest < ActiveRecord::TestCase - def test_quoting_classes - assert_equal "'Object'", AbstractAdapter.new(nil).quote(Object) - end - end - end - end -end diff --git a/activerecord/test/cases/connection_adapters/schema_cache_test.rb b/activerecord/test/cases/connection_adapters/schema_cache_test.rb index d4459603af..1b4f80fc67 100644 --- a/activerecord/test/cases/connection_adapters/schema_cache_test.rb +++ b/activerecord/test/cases/connection_adapters/schema_cache_test.rb @@ -12,6 +12,33 @@ module ActiveRecord assert_equal "id", @cache.primary_keys("posts") end + def test_yaml_dump_and_load + @cache.columns("posts") + @cache.columns_hash("posts") + @cache.data_sources("posts") + @cache.primary_keys("posts") + + new_cache = YAML.load(YAML.dump(@cache)) + assert_no_queries do + assert_equal 11, new_cache.columns("posts").size + assert_equal 11, new_cache.columns_hash("posts").size + assert new_cache.data_sources("posts") + assert_equal "id", new_cache.primary_keys("posts") + end + end + + def test_yaml_loads_5_1_dump + body = File.open(schema_dump_path).read + cache = YAML.load(body) + + assert_no_queries do + assert_equal 11, cache.columns("posts").size + assert_equal 11, cache.columns_hash("posts").size + assert cache.data_sources("posts") + assert_equal "id", cache.primary_keys("posts") + end + end + def test_primary_key_for_non_existent_table assert_nil @cache.primary_keys("omgponies") end @@ -45,10 +72,12 @@ module ActiveRecord @cache = Marshal.load(Marshal.dump(@cache)) - assert_equal 11, @cache.columns("posts").size - assert_equal 11, @cache.columns_hash("posts").size - assert @cache.data_sources("posts") - assert_equal "id", @cache.primary_keys("posts") + assert_no_queries do + assert_equal 11, @cache.columns("posts").size + assert_equal 11, @cache.columns_hash("posts").size + assert @cache.data_sources("posts") + assert_equal "id", @cache.primary_keys("posts") + end end def test_table_methods_deprecation @@ -56,6 +85,12 @@ module ActiveRecord assert_deprecated { assert @cache.tables("posts") } assert_deprecated { @cache.clear_table_cache!("posts") } end + + private + + def schema_dump_path + "test/assets/schema_dump_5_1.yml" + end end end end diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index d7ff9d6880..42600e53fd 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -184,14 +184,14 @@ module ActiveRecord def test_checkout_behaviour pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec - connection = pool.connection - assert_not_nil connection + main_connection = pool.connection + assert_not_nil main_connection threads = [] 4.times do |i| threads << Thread.new(i) do - connection = pool.connection - assert_not_nil connection - connection.close + thread_connection = pool.connection + assert_not_nil thread_connection + thread_connection.close end end @@ -455,49 +455,63 @@ module ActiveRecord with_single_connection_pool do |pool| [:disconnect, :disconnect!, :clear_reloadable_connections, :clear_reloadable_connections!].each do |group_action_method| conn = pool.connection # drain the only available connection - second_thread_done = Concurrent::CountDownLatch.new - - # create a first_thread and let it get into the FIFO queue first - first_thread = Thread.new do - pool.with_connection { second_thread_done.wait } - end - - # wait for first_thread to get in queue - Thread.pass until pool.num_waiting_in_queue == 1 - - # create a different, later thread, that will attempt to do a "group action", - # but because of the group action semantics it should be able to preempt the - # first_thread when a connection is made available - second_thread = Thread.new do - pool.send(group_action_method) - second_thread_done.count_down - end + second_thread_done = Concurrent::Event.new - # wait for second_thread to get in queue - Thread.pass until pool.num_waiting_in_queue == 2 - - # return the only available connection - pool.checkin(conn) - - # if the second_thread is not able to preempt the first_thread, - # they will temporarily (until either of them timeouts with ConnectionTimeoutError) - # deadlock and a join(2) timeout will be reached - failed = true unless second_thread.join(2) - - #--- post test clean up start - second_thread_done.count_down if failed - - # after `pool.disconnect()` the first thread will be left stuck in queue, no need to wait for - # it to timeout with ConnectionTimeoutError - if (group_action_method == :disconnect || group_action_method == :disconnect!) && pool.num_waiting_in_queue > 0 - pool.with_connection {} # create a new connection in case there are threads still stuck in a queue + begin + # create a first_thread and let it get into the FIFO queue first + first_thread = Thread.new do + pool.with_connection { second_thread_done.wait } + end + + # wait for first_thread to get in queue + Thread.pass until pool.num_waiting_in_queue == 1 + + # create a different, later thread, that will attempt to do a "group action", + # but because of the group action semantics it should be able to preempt the + # first_thread when a connection is made available + second_thread = Thread.new do + pool.send(group_action_method) + second_thread_done.set + end + + # wait for second_thread to get in queue + Thread.pass until pool.num_waiting_in_queue == 2 + + # return the only available connection + pool.checkin(conn) + + # if the second_thread is not able to preempt the first_thread, + # they will temporarily (until either of them timeouts with ConnectionTimeoutError) + # deadlock and a join(2) timeout will be reached + assert second_thread.join(2), "#{group_action_method} is not able to preempt other waiting threads" + + ensure + # post test clean up + failed = !second_thread_done.set? + + if failed + second_thread_done.set + + puts + puts ">>> test_disconnect_and_clear_reloadable_connections_are_able_to_preempt_other_waiting_threads / #{group_action_method}" + p [first_thread, second_thread] + p pool.stat + p pool.connections.map(&:owner) + + first_thread.join(2) + second_thread.join(2) + + puts "---" + p [first_thread, second_thread] + p pool.stat + p pool.connections.map(&:owner) + puts "<<<" + puts + end + + first_thread.join(10) || raise("first_thread got stuck") + second_thread.join(10) || raise("second_thread got stuck") end - - first_thread.join - second_thread.join - #--- post test clean up end - - flunk "#{group_action_method} is not able to preempt other waiting threads" if failed end end end @@ -526,6 +540,26 @@ module ActiveRecord end end + def test_connection_pool_stat + with_single_connection_pool do |pool| + pool.with_connection do |connection| + stats = pool.stat + assert_equal({ size: 1, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }, stats) + end + + stats = pool.stat + assert_equal({ size: 1, connections: 1, busy: 0, dead: 0, idle: 1, waiting: 0, checkout_timeout: 5 }, stats) + + Thread.new do + pool.checkout + Thread.current.kill + end.join + + stats = pool.stat + assert_equal({ size: 1, connections: 1, busy: 0, dead: 1, idle: 0, waiting: 0, checkout_timeout: 5 }, stats) + end + end + private def with_single_connection_pool one_conn_spec = ActiveRecord::Base.connection_pool.spec.dup diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index 0f62c73f8f..13b5bae13c 100644 --- a/activerecord/test/cases/connection_specification/resolver_test.rb +++ b/activerecord/test/cases/connection_specification/resolver_test.rb @@ -4,11 +4,11 @@ module ActiveRecord module ConnectionAdapters class ConnectionSpecification class ResolverTest < ActiveRecord::TestCase - def resolve(spec, config={}) + def resolve(spec, config = {}) Resolver.new(config).resolve(spec) end - def spec(spec, config={}) + def spec(spec, config = {}) Resolver.new(config).spec(spec) end diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index fcaff38f82..6532efcf22 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -169,7 +169,7 @@ if current_adapter?(:Mysql2Adapter) assert_nil record.non_null_text assert_nil record.non_null_blob - assert_raises(ActiveRecord::StatementInvalid) { klass.create } + assert_raises(ActiveRecord::NotNullViolation) { klass.create } end end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 09bd00291d..0e58e65a07 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -341,7 +341,7 @@ class DirtyTest < ActiveRecord::TestCase def test_partial_update_with_optimistic_locking person = Person.new(first_name: "foo") - old_lock_version = 1 + old_lock_version = person.lock_version with_partial_writes Person, false do assert_queries(2) { 2.times { person.save! } } @@ -726,6 +726,89 @@ class DirtyTest < ActiveRecord::TestCase assert person.changed? end + test "saved_change_to_attribute? returns whether a change occurred in the last save" do + person = Person.create!(first_name: "Sean") + + assert person.saved_change_to_first_name? + refute person.saved_change_to_gender? + assert person.saved_change_to_first_name?(from: nil, to: "Sean") + assert person.saved_change_to_first_name?(from: nil) + assert person.saved_change_to_first_name?(to: "Sean") + refute person.saved_change_to_first_name?(from: "Jim", to: "Sean") + refute person.saved_change_to_first_name?(from: "Jim") + refute person.saved_change_to_first_name?(to: "Jim") + end + + test "saved_change_to_attribute returns the change that occurred in the last save" do + person = Person.create!(first_name: "Sean", gender: "M") + + assert_equal [nil, "Sean"], person.saved_change_to_first_name + assert_equal [nil, "M"], person.saved_change_to_gender + + person.update(first_name: "Jim") + + assert_equal ["Sean", "Jim"], person.saved_change_to_first_name + assert_nil person.saved_change_to_gender + end + + test "attribute_before_last_save returns the original value before saving" do + person = Person.create!(first_name: "Sean", gender: "M") + + assert_nil person.first_name_before_last_save + assert_nil person.gender_before_last_save + + person.first_name = "Jim" + + assert_nil person.first_name_before_last_save + assert_nil person.gender_before_last_save + + person.save + + assert_equal "Sean", person.first_name_before_last_save + assert_equal "M", person.gender_before_last_save + end + + test "saved_changes? returns whether the last call to save changed anything" do + person = Person.create!(first_name: "Sean") + + assert person.saved_changes? + + person.save + + refute person.saved_changes? + end + + test "saved_changes returns a hash of all the changes that occurred" do + person = Person.create!(first_name: "Sean", gender: "M") + + assert_equal [nil, "Sean"], person.saved_changes[:first_name] + assert_equal [nil, "M"], person.saved_changes[:gender] + assert_equal %w(id first_name gender created_at updated_at).sort, person.saved_changes.keys.sort + + travel(1.second) do + person.update(first_name: "Jim") + end + + assert_equal ["Sean", "Jim"], person.saved_changes[:first_name] + assert_equal %w(first_name lock_version updated_at).sort, person.saved_changes.keys.sort + end + + test "changed? in after callbacks returns true but is deprecated" do + klass = Class.new(ActiveRecord::Base) do + self.table_name = "people" + + after_save do + ActiveSupport::Deprecation.silence do + raise "changed? should be true" unless changed? + end + raise "has_changes_to_save? should be false" if has_changes_to_save? + end + end + + person = klass.create!(first_name: "Sean") + refute person.changed? + end + private def with_partial_writes(klass, on = true) old = klass.partial_writes? diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 51563b347c..d6d24004fe 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -49,22 +49,22 @@ class FinderTest < ActiveRecord::TestCase end def test_find_with_ids_returning_ordered - records = Topic.find([4,2,5]) + records = Topic.find([4, 2, 5]) assert_equal "The Fourth Topic of the day", records[0].title assert_equal "The Second Topic of the day", records[1].title assert_equal "The Fifth Topic of the day", records[2].title - records = Topic.find(4,2,5) + records = Topic.find(4, 2, 5) assert_equal "The Fourth Topic of the day", records[0].title assert_equal "The Second Topic of the day", records[1].title assert_equal "The Fifth Topic of the day", records[2].title - records = Topic.find(["4","2","5"]) + records = Topic.find(["4", "2", "5"]) assert_equal "The Fourth Topic of the day", records[0].title assert_equal "The Second Topic of the day", records[1].title assert_equal "The Fifth Topic of the day", records[2].title - records = Topic.find("4","2","5") + records = Topic.find("4", "2", "5") assert_equal "The Fourth Topic of the day", records[0].title assert_equal "The Second Topic of the day", records[1].title assert_equal "The Fifth Topic of the day", records[2].title @@ -72,12 +72,12 @@ class FinderTest < ActiveRecord::TestCase def test_find_with_ids_and_order_clause # The order clause takes precedence over the informed ids - records = Topic.order(:author_name).find([5,3,1]) + records = Topic.order(:author_name).find([5, 3, 1]) assert_equal "The Third Topic of the day", records[0].title assert_equal "The First Topic", records[1].title assert_equal "The Fifth Topic of the day", records[2].title - records = Topic.order(:id).find([5,3,1]) + records = Topic.order(:id).find([5, 3, 1]) assert_equal "The First Topic", records[0].title assert_equal "The Third Topic of the day", records[1].title assert_equal "The Fifth Topic of the day", records[2].title @@ -85,14 +85,14 @@ class FinderTest < ActiveRecord::TestCase def test_find_with_ids_with_limit_and_order_clause # The order clause takes precedence over the informed ids - records = Topic.limit(2).order(:id).find([5,3,1]) + records = Topic.limit(2).order(:id).find([5, 3, 1]) assert_equal 2, records.size assert_equal "The First Topic", records[0].title assert_equal "The Third Topic of the day", records[1].title end def test_find_with_ids_and_limit - records = Topic.limit(3).find([3,2,5,1,4]) + records = Topic.limit(3).find([3, 2, 5, 1, 4]) assert_equal 3, records.size assert_equal "The Third Topic of the day", records[0].title assert_equal "The Second Topic of the day", records[1].title @@ -102,7 +102,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 an ActiveRecord::RecordNotFound - records = Topic.where(approved: true).limit(3).find([3,2,5,1,4]) + 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 assert_equal "The Second Topic of the day", records[1].title @@ -110,7 +110,7 @@ class FinderTest < ActiveRecord::TestCase end def test_find_with_ids_and_offset - records = Topic.offset(2).find([3,2,5,1,4]) + records = Topic.offset(2).find([3, 2, 5, 1, 4]) assert_equal 3, records.size assert_equal "The Fifth Topic of the day", records[0].title assert_equal "The First Topic", records[1].title @@ -136,7 +136,7 @@ class FinderTest < ActiveRecord::TestCase # find should handle strings that come from URLs # (example: Category.find(params[:id])) def test_find_with_string - assert_equal(Topic.find(1).title,Topic.find("1").title) + assert_equal(Topic.find(1).title, Topic.find("1").title) end def test_exists @@ -151,7 +151,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal false, Topic.exists?(45) assert_equal false, Topic.exists?(Topic.new.id) - assert_raise(NoMethodError) { Topic.exists?([1,2]) } + assert_raise(NoMethodError) { Topic.exists?([1, 2]) } end def test_exists_with_polymorphic_relation @@ -175,7 +175,7 @@ class FinderTest < ActiveRecord::TestCase def test_exists_returns_false_when_parameter_has_invalid_type assert_equal false, Topic.exists?("foo") - assert_equal false, Topic.exists?(("9"*53).to_i) # number that's bigger than int + assert_equal false, Topic.exists?(("9" * 53).to_i) # number that's bigger than int end def test_exists_does_not_select_columns_without_alias @@ -258,8 +258,8 @@ class FinderTest < ActiveRecord::TestCase end def test_find_by_ids_with_limit_and_offset - assert_equal 2, Entrant.limit(2).find([1,3,2]).size - entrants = Entrant.limit(3).offset(2).find([1,3,2]) + assert_equal 2, Entrant.limit(2).find([1, 3, 2]).size + entrants = Entrant.limit(3).offset(2).find([1, 3, 2]) assert_equal 1, entrants.size assert_equal "Ruby Guru", entrants.first.name @@ -488,12 +488,12 @@ class FinderTest < ActiveRecord::TestCase assert_equal topics(:fourth), Topic.offset(1).second_to_last assert_equal topics(:fourth), Topic.offset(2).second_to_last assert_equal topics(:fourth), Topic.offset(3).second_to_last - assert_equal nil, Topic.offset(4).second_to_last - assert_equal nil, Topic.offset(5).second_to_last + assert_nil Topic.offset(4).second_to_last + assert_nil Topic.offset(5).second_to_last #test with limit - # assert_equal nil, Topic.limit(1).second # TODO: currently failing - assert_equal nil, Topic.limit(1).second_to_last + # assert_nil Topic.limit(1).second # TODO: currently failing + assert_nil Topic.limit(1).second_to_last end def test_second_to_last_have_primary_key_order_by_default @@ -516,15 +516,15 @@ class FinderTest < ActiveRecord::TestCase # test with offset assert_equal topics(:third), Topic.offset(1).third_to_last assert_equal topics(:third), Topic.offset(2).third_to_last - assert_equal nil, Topic.offset(3).third_to_last - assert_equal nil, Topic.offset(4).third_to_last - assert_equal nil, Topic.offset(5).third_to_last + assert_nil Topic.offset(3).third_to_last + assert_nil Topic.offset(4).third_to_last + assert_nil Topic.offset(5).third_to_last # test with limit - # assert_equal nil, Topic.limit(1).third # TODO: currently failing - assert_equal nil, Topic.limit(1).third_to_last - # assert_equal nil, Topic.limit(2).third # TODO: currently failing - assert_equal nil, Topic.limit(2).third_to_last + # assert_nil Topic.limit(1).third # TODO: currently failing + assert_nil Topic.limit(1).third_to_last + # assert_nil Topic.limit(2).third # TODO: currently failing + assert_nil Topic.limit(2).third_to_last end def test_third_to_last_have_primary_key_order_by_default @@ -584,7 +584,7 @@ class FinderTest < ActiveRecord::TestCase end def test_last_on_loaded_relation_should_not_use_sql - relation = Topic.limit(10).load + relation = Topic.limit(10).load assert_no_queries do relation.last relation.last(2) @@ -693,27 +693,27 @@ class FinderTest < ActiveRecord::TestCase end def test_find_on_hash_conditions_with_range - assert_equal [1,2], Topic.where(id: 1..2).to_a.map(&:id).sort + assert_equal [1, 2], Topic.where(id: 1..2).to_a.map(&:id).sort assert_raise(ActiveRecord::RecordNotFound) { Topic.where(id: 2..3).find(1) } end def test_find_on_hash_conditions_with_end_exclusive_range - assert_equal [1,2,3], Topic.where(id: 1..3).to_a.map(&:id).sort - assert_equal [1,2], Topic.where(id: 1...3).to_a.map(&:id).sort + assert_equal [1, 2, 3], Topic.where(id: 1..3).to_a.map(&:id).sort + assert_equal [1, 2], Topic.where(id: 1...3).to_a.map(&:id).sort assert_raise(ActiveRecord::RecordNotFound) { Topic.where(id: 2...3).find(3) } end def test_find_on_hash_conditions_with_multiple_ranges - assert_equal [1,2,3], Comment.where(id: 1..3, post_id: 1..2).to_a.map(&:id).sort + assert_equal [1, 2, 3], Comment.where(id: 1..3, post_id: 1..2).to_a.map(&:id).sort assert_equal [1], Comment.where(id: 1..1, post_id: 1..10).to_a.map(&:id).sort end def test_find_on_hash_conditions_with_array_of_integers_and_ranges - assert_equal [1,2,3,5,6,7,8,9], Comment.where(id: [1..2, 3, 5, 6..8, 9]).to_a.map(&:id).sort + assert_equal [1, 2, 3, 5, 6, 7, 8, 9], Comment.where(id: [1..2, 3, 5, 6..8, 9]).to_a.map(&:id).sort end def test_find_on_hash_conditions_with_array_of_ranges - assert_equal [1,2,6,7,8], Comment.where(id: [1..2, 6..8]).to_a.map(&:id).sort + assert_equal [1, 2, 6, 7, 8], Comment.where(id: [1..2, 6..8]).to_a.map(&:id).sort end def test_find_on_multiple_hash_conditions @@ -983,7 +983,6 @@ class FinderTest < ActiveRecord::TestCase assert_equal devs[2], Developer.offset(2).first assert_equal devs[-3], Developer.offset(2).last - assert_equal devs[-3], Developer.offset(2).last assert_equal devs[-3], Developer.offset(2).order("id DESC").first end @@ -1029,7 +1028,7 @@ class FinderTest < ActiveRecord::TestCase def test_find_by_id_with_conditions_with_or assert_nothing_raised do - Post.where("posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'").find([1,2,3]) + Post.where("posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'").find([1, 2, 3]) end end @@ -1061,8 +1060,8 @@ class FinderTest < ActiveRecord::TestCase end def test_select_values - assert_equal ["1","2","3","4","5","6","7","8","9", "10", "11"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map!(&:to_s) - assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex"], Company.connection.select_values("SELECT name FROM companies ORDER BY id") + assert_equal ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map!(&:to_s) + assert_equal ["37signals", "Summit", "Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex"], Company.connection.select_values("SELECT name FROM companies ORDER BY id") end def test_select_rows @@ -1167,12 +1166,12 @@ class FinderTest < ActiveRecord::TestCase end test "find_by returns nil if the record is missing" do - assert_equal nil, Post.find_by("1 = 0") + assert_nil Post.find_by("1 = 0") end test "find_by with associations" do assert_equal authors(:david), Post.find_by(author: authors(:david)).author - assert_equal authors(:mary) , Post.find_by(author: authors(:mary) ).author + assert_equal authors(:mary) , Post.find_by(author: authors(:mary)).author end test "find_by doesn't have implicit ordering" do @@ -1221,7 +1220,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal tyre2, zyke.tyres.custom_find_by(id: tyre2.id) end - protected + private def table_with_custom_primary_key yield(Class.new(Toy) do def self.name diff --git a/activerecord/test/cases/fixture_set/file_test.rb b/activerecord/test/cases/fixture_set/file_test.rb index cf2a73595a..533edcc2e0 100644 --- a/activerecord/test/cases/fixture_set/file_test.rb +++ b/activerecord/test/cases/fixture_set/file_test.rb @@ -31,7 +31,7 @@ module ActiveRecord def test_values File.open(::File.join(FIXTURES_ROOT, "accounts.yml")) do |fh| - assert_equal [1,2,3,4,5,6].sort, fh.to_a.map(&:last).map { |x| + assert_equal [1, 2, 3, 4, 5, 6].sort, fh.to_a.map(&:last).map { |x| x["id"] }.sort end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 3f111447ff..dd48053823 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -12,9 +12,11 @@ require "models/company" require "models/computer" require "models/course" require "models/developer" +require "models/dog" require "models/doubloon" require "models/joke" require "models/matey" +require "models/other_dog" require "models/parrot" require "models/pirate" require "models/post" @@ -192,28 +194,38 @@ class FixturesTest < ActiveRecord::TestCase end def test_empty_yaml_fixture - assert_not_nil ActiveRecord::FixtureSet.new( Account.connection, "accounts", Account, FIXTURES_ROOT + "/naked/yml/accounts") + assert_not_nil ActiveRecord::FixtureSet.new(Account.connection, "accounts", Account, FIXTURES_ROOT + "/naked/yml/accounts") end def test_empty_yaml_fixture_with_a_comment_in_it - assert_not_nil ActiveRecord::FixtureSet.new( Account.connection, "companies", Company, FIXTURES_ROOT + "/naked/yml/companies") + assert_not_nil ActiveRecord::FixtureSet.new(Account.connection, "companies", Company, FIXTURES_ROOT + "/naked/yml/companies") end def test_nonexistent_fixture_file nonexistent_fixture_path = FIXTURES_ROOT + "/imnothere" #sanity check to make sure that this file never exists - assert Dir[nonexistent_fixture_path+"*"].empty? + assert Dir[nonexistent_fixture_path + "*"].empty? assert_raise(Errno::ENOENT) do - ActiveRecord::FixtureSet.new( Account.connection, "companies", Company, nonexistent_fixture_path) + ActiveRecord::FixtureSet.new(Account.connection, "companies", Company, nonexistent_fixture_path) end end def test_dirty_dirty_yaml_file - assert_raise(ActiveRecord::Fixture::FormatError) do - ActiveRecord::FixtureSet.new( Account.connection, "courses", Course, FIXTURES_ROOT + "/naked/yml/courses") + fixture_path = FIXTURES_ROOT + "/naked/yml/courses" + error = assert_raise(ActiveRecord::Fixture::FormatError) do + ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path) end + assert_equal "fixture is not a hash: #{fixture_path}.yml", error.to_s + end + + def test_yaml_file_with_one_invalid_fixture + fixture_path = FIXTURES_ROOT + "/naked/yml/courses_with_invalid_key" + error = assert_raise(ActiveRecord::Fixture::FormatError) do + ActiveRecord::FixtureSet.new(Account.connection, "courses", Course, fixture_path) + end + assert_equal "fixture key is not a hash: #{fixture_path}.yml, keys: [\"two\"]", error.to_s end def test_yaml_file_with_invalid_column @@ -948,7 +960,7 @@ end class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase ActiveRecord::FixtureSet.reset_cache - set_fixture_class :randomly_named_a9 => + set_fixture_class :randomly_named_a9 => ClassNameThatDoesNotFollowCONVENTIONS, :'admin/randomly_named_a9' => Admin::ClassNameThatDoesNotFollowCONVENTIONS1, @@ -1011,3 +1023,16 @@ class FixtureClassNamesTest < ActiveRecord::TestCase assert_nil fixture_class_names["unregistered_identifier"] end end + +class SameNameDifferentDatabaseFixturesTest < ActiveRecord::TestCase + fixtures :dogs, :other_dogs + + test "fixtures are properly loaded" do + # Force loading the fixtures again to reproduce issue + ActiveRecord::FixtureSet.reset_cache + create_fixtures("dogs", "other_dogs") + + assert_kind_of Dog, dogs(:sophie) + assert_kind_of OtherDog, other_dogs(:lassie) + end +end diff --git a/activerecord/test/cases/forbidden_attributes_protection_test.rb b/activerecord/test/cases/forbidden_attributes_protection_test.rb index 75c3493527..ffa3f63e0d 100644 --- a/activerecord/test/cases/forbidden_attributes_protection_test.rb +++ b/activerecord/test/cases/forbidden_attributes_protection_test.rb @@ -144,7 +144,7 @@ class ForbiddenAttributesProtectionTest < ActiveRecord::TestCase end def test_strong_params_style_objects_work_with_singular_associations - params = ProtectedParams.new( name: "Stern", ship_attributes: ProtectedParams.new(name: "The Black Rock").permit!).permit! + params = ProtectedParams.new(name: "Stern", ship_attributes: ProtectedParams.new(name: "The Black Rock").permit!).permit! part = ShipPart.new(params) assert_equal "Stern", part.name @@ -155,7 +155,7 @@ class ForbiddenAttributesProtectionTest < ActiveRecord::TestCase params = ProtectedParams.new( trinkets_attributes: ProtectedParams.new( "0" => ProtectedParams.new(name: "Necklace").permit!, - "1" => ProtectedParams.new(name: "Spoon").permit! ) ).permit! + "1" => ProtectedParams.new(name: "Spoon").permit!)).permit! part = ShipPart.new(params) assert_equal "Necklace", part.trinkets[0].name diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 00457965d7..d7aa091623 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -15,7 +15,7 @@ class IntegrationTest < ActiveRecord::TestCase def test_to_param_returns_nil_if_not_persisted client = Client.new - assert_equal nil, client.to_param + assert_nil client.to_param end def test_to_param_returns_id_if_not_persisted_but_id_is_set @@ -89,7 +89,7 @@ class IntegrationTest < ActiveRecord::TestCase def test_to_param_class_method_uses_default_if_not_persisted firm = Firm.new(name: "Fancy Shirts") - assert_equal nil, firm.to_param + assert_nil firm.to_param end def test_to_param_with_no_arguments diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index b06fed4f0d..155e858822 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -102,7 +102,7 @@ class JsonSerializationTest < ActiveRecord::TestCase end def test_uses_serializable_hash_with_only_option - def @contact.serializable_hash(options=nil) + def @contact.serializable_hash(options = nil) super(only: %w(name)) end @@ -113,7 +113,7 @@ class JsonSerializationTest < ActiveRecord::TestCase end def test_uses_serializable_hash_with_except_option - def @contact.serializable_hash(options=nil) + def @contact.serializable_hash(options = nil) super(except: %w(age)) end @@ -137,7 +137,7 @@ class JsonSerializationTest < ActiveRecord::TestCase @contact = ContactSti.new(@contact.attributes) assert_equal "ContactSti", @contact.type - def @contact.serializable_hash(options={}) + def @contact.serializable_hash(options = {}) super({ except: %w(age) }.merge!(options)) end @@ -243,7 +243,7 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase assert !@david.posts.first.respond_to?(:favorite_quote) assert_match %r{"favorite_quote":"Constraints are liberating"}, json - assert_equal %r{"favorite_quote":}.match(json).size, 1 + assert_equal 1, %r{"favorite_quote":}.match(json).size end def test_should_allow_only_option_for_list_of_authors diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 13b6f6daaf..95fb670dac 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -161,14 +161,6 @@ class OptimisticLockingTest < ActiveRecord::TestCase assert_equal(error.record.object_id, p2.object_id) end - def test_lock_new_with_nil - p1 = Person.new(first_name: "anika") - p1.save! - p1.lock_version = nil # simulate bad fixture or column with no default - p1.save! - assert_equal 1, p1.lock_version - end - def test_lock_new_when_explicitly_passing_nil p1 = Person.new(first_name: "anika", lock_version: nil) p1.save! @@ -222,22 +214,149 @@ class OptimisticLockingTest < ActiveRecord::TestCase def test_lock_without_default_sets_version_to_zero t1 = LockWithoutDefault.new + + assert_equal 0, t1.lock_version + assert_nil t1.lock_version_before_type_cast + + t1.save! + t1.reload + assert_equal 0, t1.lock_version + assert_equal 0, t1.lock_version_before_type_cast + end + + def test_lock_without_default_should_work_with_null_in_the_database + ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults(title) VALUES('title1')") + t1 = LockWithoutDefault.last + t2 = LockWithoutDefault.last + + assert_equal 0, t1.lock_version + assert_nil t1.lock_version_before_type_cast + assert_equal 0, t2.lock_version + assert_nil t2.lock_version_before_type_cast + + t1.title = "new title1" + t2.title = "new title2" + + assert_nothing_raised { t1.save! } + assert_equal 1, t1.lock_version + assert_equal "new title1", t1.title + + assert_raise(ActiveRecord::StaleObjectError) { t2.save! } + assert_equal 0, t2.lock_version + assert_equal "new title2", t2.title + end + + def test_lock_without_default_should_update_with_lock_col + t1 = LockWithoutDefault.create(title: "title1", lock_version: 6) + + assert_equal 6, t1.lock_version + + t1.update(lock_version: 0) + t1.reload - t1.save - t1 = LockWithoutDefault.find(t1.id) assert_equal 0, t1.lock_version end + def test_lock_without_default_queries_count + t1 = LockWithoutDefault.create(title: "title1") + + assert_equal "title1", t1.title + assert_equal 0, t1.lock_version + + assert_queries(1) { t1.update(title: "title2") } + + t1.reload + assert_equal "title2", t1.title + assert_equal 1, t1.lock_version + + assert_queries(1) { t1.update(title: "title3", lock_version: 6) } + + t1.reload + assert_equal "title3", t1.title + assert_equal 6, t1.lock_version + + t2 = LockWithoutDefault.new(title: "title1") + + assert_queries(1) { t2.save! } + + t2.reload + assert_equal "title1", t2.title + assert_equal 0, t2.lock_version + end + def test_lock_with_custom_column_without_default_sets_version_to_zero t1 = LockWithCustomColumnWithoutDefault.new + assert_equal 0, t1.custom_lock_version assert_nil t1.custom_lock_version_before_type_cast t1.save! t1.reload + + assert_equal 0, t1.custom_lock_version + assert_equal 0, t1.custom_lock_version_before_type_cast + end + + def test_lock_with_custom_column_without_default_should_work_with_null_in_the_database + ActiveRecord::Base.connection.execute("INSERT INTO lock_without_defaults_cust(title) VALUES('title1')") + + t1 = LockWithCustomColumnWithoutDefault.last + t2 = LockWithCustomColumnWithoutDefault.last + assert_equal 0, t1.custom_lock_version - assert [0, "0"].include?(t1.custom_lock_version_before_type_cast) + assert_nil t1.custom_lock_version_before_type_cast + assert_equal 0, t2.custom_lock_version + assert_nil t2.custom_lock_version_before_type_cast + + t1.title = "new title1" + t2.title = "new title2" + + assert_nothing_raised { t1.save! } + assert_equal 1, t1.custom_lock_version + assert_equal "new title1", t1.title + + assert_raise(ActiveRecord::StaleObjectError) { t2.save! } + assert_equal 0, t2.custom_lock_version + assert_equal "new title2", t2.title + end + + def test_lock_with_custom_column_without_default_should_update_with_lock_col + t1 = LockWithCustomColumnWithoutDefault.create(title: "title1", custom_lock_version: 6) + + assert_equal 6, t1.custom_lock_version + + t1.update(custom_lock_version: 0) + t1.reload + + assert_equal 0, t1.custom_lock_version + end + + def test_lock_with_custom_column_without_default_queries_count + t1 = LockWithCustomColumnWithoutDefault.create(title: "title1") + + assert_equal "title1", t1.title + assert_equal 0, t1.custom_lock_version + + assert_queries(1) { t1.update(title: "title2") } + + t1.reload + assert_equal "title2", t1.title + assert_equal 1, t1.custom_lock_version + + assert_queries(1) { t1.update(title: "title3", custom_lock_version: 6) } + + t1.reload + assert_equal "title3", t1.title + assert_equal 6, t1.custom_lock_version + + t2 = LockWithCustomColumnWithoutDefault.new(title: "title1") + + assert_queries(1) { t2.save! } + + t2.reload + assert_equal "title1", t2.title + assert_equal 0, t2.custom_lock_version end def test_readonly_attributes @@ -351,7 +470,7 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase private - def add_counter_column_to(model, col="test_count") + def add_counter_column_to(model, col = "test_count") model.connection.add_column model.table_name, col, :integer, null: false, default: 0 model.reset_column_information end @@ -460,7 +579,8 @@ unless in_memory_db? assert first.end > second.end end - protected + private + def duel(zzz = 5) t0, t1, t2, t3 = nil, nil, nil, nil diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index bdb90eaa74..03f9c4a9ed 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -43,7 +43,7 @@ module ActiveRecord t.column :foo, :string, null: false end - assert_raises(ActiveRecord::StatementInvalid) do + assert_raises(ActiveRecord::NotNullViolation) do connection.execute "insert into testings (foo) values (NULL)" end end @@ -233,7 +233,7 @@ module ActiveRecord end connection.add_column :testings, :bar, :string, null: false - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::NotNullViolation) do connection.execute "insert into testings (foo, bar) values ('hello', NULL)" end end @@ -244,12 +244,16 @@ module ActiveRecord t.column :foo, :string end - con = connection - connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')" - assert_nothing_raised { connection.add_column :testings, :bar, :string, null: false, default: "default" } + quoted_id = connection.quote_column_name("id") + quoted_foo = connection.quote_column_name("foo") + quoted_bar = connection.quote_column_name("bar") + connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}) values (1, 'hello')") + assert_nothing_raised do + connection.add_column :testings, :bar, :string, null: false, default: "default" + end - assert_raises(ActiveRecord::StatementInvalid) do - connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)" + assert_raises(ActiveRecord::NotNullViolation) do + connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}, #{quoted_bar}) values (2, 'hello', NULL)") end end diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index ec817a579b..8a4242cf1d 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -101,7 +101,12 @@ module ActiveRecord def test_primary_key_creates_primary_key_column with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, primary_key: true, first: true] + if current_adapter?(:Mysql2Adapter) + @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, { first: true, auto_increment: true, limit: 8, primary_key: true }] + else + @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, primary_key: true, first: true] + end + t.primary_key :id, first: true end end diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index cab2069754..9be6667aa1 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -76,7 +76,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? end def test_add_foreign_key_with_non_standard_primary_key - with_example_table @connection, "space_shuttles", "pk integer PRIMARY KEY" do + with_example_table @connection, "space_shuttles", "pk BIGINT PRIMARY KEY" do @connection.add_foreign_key(:astronauts, :space_shuttles, column: "rocket_id", primary_key: "pk", name: "custom_pk") @@ -101,7 +101,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? fk = foreign_keys.first if current_adapter?(:Mysql2Adapter) # ON DELETE RESTRICT is the default on MySQL - assert_equal nil, fk.on_delete + assert_nil fk.on_delete else assert_equal :restrict, fk.on_delete end @@ -229,7 +229,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? create_table("cities") { |t| } create_table("houses") do |t| - t.column :city_id, :integer + t.column :city_id, :bigint end add_foreign_key :houses, :cities, column: "city_id" @@ -261,7 +261,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? create_table(:schools) create_table(:classes) do |t| - t.column :school_id, :integer + t.column :school_id, :bigint end add_foreign_key :classes, :schools end diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 528811db49..4957ab8b3d 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -42,7 +42,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? test "options hash can be passed" do @connection.change_table :testing_parents do |t| - t.integer :other_id + t.bigint :other_id t.index :other_id, unique: true end @connection.create_table :testings do |t| @@ -92,7 +92,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? test "foreign keys accept options when changing the table" do @connection.change_table :testing_parents do |t| - t.integer :other_id + t.bigint :other_id t.index :other_id, unique: true end @connection.create_table :testings @@ -177,8 +177,8 @@ if ActiveRecord::Base.connection.supports_foreign_keys? 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.bigint :col_1 + t.bigint :col_2 t.foreign_key :testing_parents, column: :col_1 t.foreign_key :testing_parents, column: :col_2 diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index 8fbe60f24e..df15d7cb45 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -57,7 +57,7 @@ module ActiveRecord def test_creates_named_unique_index add_reference table_name, :tag, index: { name: "index_taggings_on_tag_id", unique: true } - assert index_exists?(table_name, :tag_id, name: "index_taggings_on_tag_id", unique: true ) + assert index_exists?(table_name, :tag_id, name: "index_taggings_on_tag_id", unique: true) end def test_creates_reference_id_with_specified_type diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 151f3c8efd..082cfd3242 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -388,7 +388,7 @@ class MigrationTest < ActiveRecord::TestCase 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 + new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call refute_equal current_env, new_env @@ -413,7 +413,7 @@ class MigrationTest < ActiveRecord::TestCase 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 + new_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call refute_equal current_env, new_env @@ -429,14 +429,14 @@ class MigrationTest < ActiveRecord::TestCase def test_internal_metadata_stores_environment_when_other_data_exists ActiveRecord::InternalMetadata.delete_all - ActiveRecord::InternalMetadata[:foo] = "bar" + ActiveRecord::InternalMetadata[:foo] = "bar" current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call migrations_path = MIGRATIONS_ROOT + "/valid" old_path = ActiveRecord::Migrator.migrations_paths ActiveRecord::Migrator.migrations_paths = migrations_path - current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call + current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call ActiveRecord::Migrator.up(migrations_path) assert_equal current_env, ActiveRecord::InternalMetadata[:environment] assert_equal "bar", ActiveRecord::InternalMetadata[:foo] @@ -705,7 +705,7 @@ class MigrationTest < ActiveRecord::TestCase end end - protected + private # This is needed to isolate class_attribute assignments like `table_name_prefix` # for each test case. def new_isolated_reminder_class diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 1ba18bc9c2..b775bf0492 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -11,7 +11,7 @@ class MigratorTest < ActiveRecord::TestCase def initialize(name = self.class.name, version = nil) super - @went_up = false + @went_up = false @went_down = false end @@ -344,10 +344,10 @@ class MigratorTest < ActiveRecord::TestCase _, migrator = migrator_class(3) migrator.migrate("valid") - assert_equal([1,2,3], ActiveRecord::Migrator.get_all_versions) + assert_equal([1, 2, 3], ActiveRecord::Migrator.get_all_versions) migrator.rollback("valid") - assert_equal([1,2], ActiveRecord::Migrator.get_all_versions) + assert_equal([1, 2], ActiveRecord::Migrator.get_all_versions) migrator.rollback("valid") assert_equal([1], ActiveRecord::Migrator.get_all_versions) @@ -368,7 +368,7 @@ class MigratorTest < ActiveRecord::TestCase def sensors(count) calls = [] migrations = count.times.map { |i| - m(nil, i + 1) { |c,migration| + m(nil, i + 1) { |c, migration| calls << [c, migration.version] } } diff --git a/activerecord/test/cases/multiparameter_attributes_test.rb b/activerecord/test/cases/multiparameter_attributes_test.rb index b2f76398df..ceb5724377 100644 --- a/activerecord/test/cases/multiparameter_attributes_test.rb +++ b/activerecord/test/cases/multiparameter_attributes_test.rb @@ -260,6 +260,13 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase topic.attributes = attributes assert_equal Time.zone.local(2000, 1, 1, 16, 24, 0), topic.bonus_time assert_not topic.bonus_time.utc? + + attributes = { + "written_on(1i)" => "2000", "written_on(2i)" => "", "written_on(3i)" => "", + "written_on(4i)" => "", "written_on(5i)" => "" + } + topic.attributes = attributes + assert_nil topic.written_on end ensure Topic.reset_column_information @@ -280,14 +287,14 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase unless current_adapter? :OracleAdapter def test_multiparameter_attributes_setting_time_attribute - topic = Topic.new( "bonus_time(4i)"=> "01", "bonus_time(5i)" => "05" ) + topic = Topic.new("bonus_time(4i)" => "01", "bonus_time(5i)" => "05") assert_equal 1, topic.bonus_time.hour assert_equal 5, topic.bonus_time.min end end def test_multiparameter_attributes_setting_date_attribute - topic = Topic.new( "written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11" ) + topic = Topic.new("written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11") assert_equal 1952, topic.written_on.year assert_equal 3, topic.written_on.month assert_equal 11, topic.written_on.day @@ -308,8 +315,8 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase end def test_multiparameter_attributes_setting_time_but_not_date_on_date_field - assert_raise( ActiveRecord::MultiparameterAssignmentErrors ) do - Topic.new( "written_on(4i)" => "13", "written_on(5i)" => "55" ) + assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + Topic.new("written_on(4i)" => "13", "written_on(5i)" => "55") end end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index a9c3733c20..b87419d203 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -971,7 +971,7 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase def test_attr_accessor_of_child_should_be_value_provided_during_update @owner = owners(:ashley) @pet1 = pets(:chew) - attributes = { pets_attributes: { "1"=> { id: @pet1.id, + attributes = { pets_attributes: { "1" => { id: @pet1.id, name: "Foo2", current_user: "John", _destroy: true } } } @@ -1030,13 +1030,13 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR end test "if association is not loaded and association record is saved and then in memory record attributes should be saved" do - @ship.parts_attributes=[{ id: @part.id,name: "Deck" }] + @ship.parts_attributes = [{ id: @part.id, name: "Deck" }] assert_equal 1, @ship.association(:parts).target.size assert_equal "Deck", @ship.parts[0].name end test "if association is not loaded and child doesn't change and I am saving a grandchild then in memory record should be used" do - @ship.parts_attributes=[{ id: @part.id,trinkets_attributes: [{ id: @trinket.id, name: "Ruby" }] }] + @ship.parts_attributes = [{ id: @part.id, trinkets_attributes: [{ id: @trinket.id, name: "Ruby" }] }] assert_equal 1, @ship.association(:parts).target.size assert_equal "Mast", @ship.parts[0].name assert_no_difference("@ship.parts[0].association(:trinkets).target.size") do diff --git a/activerecord/test/cases/nested_attributes_with_callbacks_test.rb b/activerecord/test/cases/nested_attributes_with_callbacks_test.rb index 8954e8c7e3..350a966d40 100644 --- a/activerecord/test/cases/nested_attributes_with_callbacks_test.rb +++ b/activerecord/test/cases/nested_attributes_with_callbacks_test.rb @@ -5,13 +5,13 @@ require "models/bird" class NestedAttributesWithCallbacksTest < ActiveRecord::TestCase Pirate.has_many(:birds_with_add_load, class_name: "Bird", - before_add: proc { |p,b| + before_add: proc { |p, b| @@add_callback_called << b p.birds_with_add_load.to_a }) Pirate.has_many(:birds_with_add, class_name: "Bird", - before_add: proc { |p,b| @@add_callback_called << b }) + before_add: proc { |p, b| @@add_callback_called << b }) Pirate.accepts_nested_attributes_for(:birds_with_add_load, :birds_with_add, @@ -21,7 +21,7 @@ class NestedAttributesWithCallbacksTest < ActiveRecord::TestCase @@add_callback_called = [] @pirate = Pirate.new.tap do |pirate| pirate.catchphrase = "Don't call me!" - pirate.birds_attributes = [{ name: "Bird1" },{ name: "Bird2" }] + pirate.birds_attributes = [{ name: "Bird1" }, { name: "Bird2" }] pirate.save! end @birds = @pirate.birds.to_a @@ -37,7 +37,7 @@ class NestedAttributesWithCallbacksTest < ActiveRecord::TestCase def existing_birds_attributes @birds.map do |bird| - bird.attributes.slice("id","name") + bird.attributes.slice("id", "name") end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 688c3ed2b1..3f1da82cb4 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -90,6 +90,14 @@ class PersistenceTest < ActiveRecord::TestCase assert_equal count, Pet.joins(:toys).where(where_args).delete_all end + def test_delete_all_with_left_joins + where_args = { toys: { name: "Bone" } } + count = Pet.left_joins(:toys).where(where_args).count + + assert_equal count, 1 + assert_equal count, Pet.left_joins(:toys).where(where_args).delete_all + end + def test_delete_all_with_joins_and_where_part_is_not_hash where_args = ["toys.name = ?", "Bone"] count = Pet.joins(:toys).where(where_args).count @@ -453,6 +461,20 @@ class PersistenceTest < ActiveRecord::TestCase assert_nil Topic.find(2).last_read end + def test_update_all_with_joins + where_args = { toys: { name: "Bone" } } + count = Pet.left_joins(:toys).where(where_args).count + + assert_equal count, Pet.joins(:toys).where(where_args).update_all(name: "Bob") + end + + def test_update_all_with_left_joins + where_args = { toys: { name: "Bone" } } + count = Pet.left_joins(:toys).where(where_args).count + + assert_equal count, Pet.left_joins(:toys).where(where_args).update_all(name: "Bob") + end + def test_update_all_with_non_standard_table_name assert_equal 1, WarehouseThing.where(id: 1).update_all(["value = ?", 0]) assert_equal 0, WarehouseThing.find(1).value @@ -967,7 +989,7 @@ class PersistenceTest < ActiveRecord::TestCase self.table_name = :widgets end - instance = widget.create!( + instance = widget.create!( name: "Bob", created_at: 1.day.ago, updated_at: 1.day.ago) diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index 31d612abd1..1d72899102 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -120,7 +120,7 @@ class PrimaryKeysTest < ActiveRecord::TestCase assert_nothing_raised { MixedCaseMonkey.find(1) } end def test_find_with_multiple_ids_should_quote_pkey - assert_nothing_raised { MixedCaseMonkey.find([1,2]) } + assert_nothing_raised { MixedCaseMonkey.find([1, 2]) } end def test_instance_update_should_quote_pkey assert_nothing_raised { MixedCaseMonkey.find(1).save } @@ -129,12 +129,6 @@ class PrimaryKeysTest < ActiveRecord::TestCase assert_nothing_raised { MixedCaseMonkey.find(1).destroy } end - def test_supports_primary_key - assert_nothing_raised do - ActiveRecord::Base.connection.supports_primary_key? - end - end - if ActiveRecord::Base.connection.supports_primary_key? def test_primary_key_returns_value_if_it_exists klass = Class.new(ActiveRecord::Base) do @@ -154,7 +148,7 @@ class PrimaryKeysTest < ActiveRecord::TestCase end def test_quoted_primary_key_after_set_primary_key - k = Class.new( ActiveRecord::Base ) + k = Class.new(ActiveRecord::Base) assert_equal k.connection.quote_column_name("id"), k.quoted_primary_key k.primary_key = "foo" assert_equal k.connection.quote_column_name("foo"), k.quoted_primary_key @@ -216,6 +210,43 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase end end +class PrimaryKeyWithAutoIncrementTest < ActiveRecord::TestCase + self.use_transactional_tests = false + + class AutoIncrement < ActiveRecord::Base + end + + def setup + @connection = ActiveRecord::Base.connection + end + + def teardown + @connection.drop_table(:auto_increments, if_exists: true) + end + + def test_primary_key_with_auto_increment + @connection.create_table(:auto_increments, id: :integer, auto_increment: true, force: true) + assert_auto_incremented + end + + def test_primary_key_with_auto_increment_and_bigint + @connection.create_table(:auto_increments, id: :bigint, auto_increment: true, force: true) + assert_auto_incremented + end + + private + def assert_auto_incremented + record1 = AutoIncrement.create! + assert_not_nil record1.id + + record1.destroy + + record2 = AutoIncrement.create! + assert_not_nil record2.id + assert_operator record2.id, :>, record1.id + end +end + class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase include SchemaDumpingHelper @@ -289,85 +320,69 @@ class CompositePrimaryKeyTest < ActiveRecord::TestCase end if current_adapter?(:Mysql2Adapter) - class PrimaryKeyBigintNilDefaultTest < ActiveRecord::TestCase + class PrimaryKeyIntegerNilDefaultTest < ActiveRecord::TestCase include SchemaDumpingHelper self.use_transactional_tests = false def setup @connection = ActiveRecord::Base.connection - @connection.create_table(:bigint_defaults, id: :bigint, default: nil, force: true) + @connection.create_table(:int_defaults, id: :integer, default: nil, force: true) end def teardown - @connection.drop_table :bigint_defaults, if_exists: true + @connection.drop_table :int_defaults, if_exists: true end - test "primary key with bigint allows default override via nil" do - column = @connection.columns(:bigint_defaults).find { |c| c.name == "id" } - assert column.bigint? + test "primary key with integer allows default override via nil" do + column = @connection.columns(:int_defaults).find { |c| c.name == "id" } + assert_equal :integer, column.type assert_not column.auto_increment? end - test "schema dump primary key with bigint default nil" do - schema = dump_table_schema "bigint_defaults" - assert_match %r{create_table "bigint_defaults", id: :bigint, default: nil}, schema + test "schema dump primary key with int default nil" do + schema = dump_table_schema "int_defaults" + assert_match %r{create_table "int_defaults", id: :integer, default: nil}, schema end end end -if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) - class PrimaryKeyBigSerialTest < ActiveRecord::TestCase - include SchemaDumpingHelper +class PrimaryKeyIntegerTest < ActiveRecord::TestCase + include SchemaDumpingHelper - self.use_transactional_tests = false + self.use_transactional_tests = false - class Widget < ActiveRecord::Base - end + class Widget < ActiveRecord::Base + end - setup do - @connection = ActiveRecord::Base.connection - if current_adapter?(:PostgreSQLAdapter) - @connection.create_table(:widgets, id: :bigserial, force: true) - else - @connection.create_table(:widgets, id: :bigint, force: true) - end - end + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table(:widgets, force: true) + end - teardown do - @connection.drop_table :widgets, if_exists: true - Widget.reset_column_information - end + teardown do + @connection.drop_table :widgets, if_exists: true + Widget.reset_column_information + end - test "primary key column type with bigserial" do - column_type = Widget.type_for_attribute(Widget.primary_key) - assert_equal :integer, column_type.type - assert_equal 8, column_type.limit + if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) + test "schema dump primary key with bigserial" do + schema = dump_table_schema "widgets" + assert_match %r{create_table "widgets", force: :cascade}, schema end + end - test "primary key with bigserial are automatically numbered" do - widget = Widget.create! - assert_not_nil widget.id - end + test "primary key column type" do + column_type = Widget.type_for_attribute(Widget.primary_key) + assert_equal :integer, column_type.type - test "schema dump primary key with bigserial" do - schema = dump_table_schema "widgets" - if current_adapter?(:PostgreSQLAdapter) - assert_match %r{create_table "widgets", id: :bigserial, force: :cascade}, schema - else - assert_match %r{create_table "widgets", id: :bigint, force: :cascade}, schema - end + if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) + assert_equal 8, column_type.limit end if current_adapter?(:Mysql2Adapter) - test "primary key column type with options" do - @connection.create_table(:widgets, id: :primary_key, limit: 8, unsigned: true, force: true) - column = @connection.columns(:widgets).find { |c| c.name == "id" } - assert column.auto_increment? - assert_equal :integer, column.type - assert_equal 8, column.limit - assert column.unsigned? - end + column = @connection.columns(:widgets).find { |c| c.name == "id" } + assert column.auto_increment? end end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 16cf2bd2d0..4a49bfe9b1 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -10,13 +10,34 @@ class QueryCacheTest < ActiveRecord::TestCase fixtures :tasks, :topics, :categories, :posts, :categories_posts - teardown do + class ShouldNotHaveExceptionsLogger < ActiveRecord::LogSubscriber + attr_reader :logger + + def initialize + super + @logger = ::Logger.new File::NULL + @exception = false + end + + def exception? + @exception + end + + def sql(event) + super + rescue + @exception = true + end + end + + def teardown Task.connection.clear_query_cache ActiveRecord::Base.connection.disable_query_cache! + super end def test_exceptional_middleware_clears_and_disables_cache_on_error - assert !ActiveRecord::Base.connection.query_cache_enabled, "cache off" + assert_cache :off mw = middleware { |env| Task.find 1 @@ -26,19 +47,66 @@ class QueryCacheTest < ActiveRecord::TestCase } assert_raises(RuntimeError) { mw.call({}) } - assert_equal 0, ActiveRecord::Base.connection.query_cache.length - assert !ActiveRecord::Base.connection.query_cache_enabled, "cache off" + assert_cache :off end - def test_exceptional_middleware_leaves_enabled_cache_alone - ActiveRecord::Base.connection.enable_query_cache! + def test_query_cache_across_threads + ActiveRecord::Base.connection_pool.connections.each do |conn| + assert_cache :off, conn + end - mw = middleware { |env| - raise "lol borked" - } - assert_raises(RuntimeError) { mw.call({}) } + assert !ActiveRecord::Base.connection.nil? + assert_cache :off - assert ActiveRecord::Base.connection.query_cache_enabled, "cache on" + middleware { + assert_cache :clean + + Task.find 1 + assert_cache :dirty + + thread_1_connection = ActiveRecord::Base.connection + ActiveRecord::Base.clear_active_connections! + assert_cache :off, thread_1_connection + + started = Concurrent::Event.new + checked = Concurrent::Event.new + + thread_2_connection = nil + thread = Thread.new { + thread_2_connection = ActiveRecord::Base.connection + + assert_equal thread_2_connection, thread_1_connection + assert_cache :off + + middleware { + assert_cache :clean + + Task.find 1 + assert_cache :dirty + + started.set + checked.wait + + ActiveRecord::Base.clear_active_connections! + }.call({}) + } + + started.wait + + thread_1_connection = ActiveRecord::Base.connection + assert_not_equal thread_1_connection, thread_2_connection + assert_cache :dirty, thread_2_connection + checked.set + thread.join + + assert_cache :off, thread_2_connection + }.call({}) + + ActiveRecord::Base.connection_pool.connections.each do |conn| + assert_cache :off, conn + end + ensure + ActiveRecord::Base.clear_all_connections! end def test_middleware_delegates @@ -62,10 +130,10 @@ class QueryCacheTest < ActiveRecord::TestCase end def test_cache_enabled_during_call - assert !ActiveRecord::Base.connection.query_cache_enabled, "cache off" + assert_cache :off mw = middleware { |env| - assert ActiveRecord::Base.connection.query_cache_enabled, "cache on" + assert_cache :clean [200, {}, nil] } mw.call({}) @@ -121,6 +189,33 @@ class QueryCacheTest < ActiveRecord::TestCase end end + def test_cache_does_not_raise_exceptions + logger = ShouldNotHaveExceptionsLogger.new + subscriber = ActiveSupport::Notifications.subscribe "sql.active_record", logger + + ActiveRecord::Base.cache do + assert_queries(1) { Task.find(1); Task.find(1) } + end + + assert_not_predicate logger, :exception? + ensure + ActiveSupport::Notifications.unsubscribe subscriber + end + + def test_query_cache_does_not_allow_sql_key_mutation + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, payload| + payload[:sql].downcase! + end + + assert_raises RuntimeError do + ActiveRecord::Base.cache do + assert_queries(1) { Task.find(1); Task.find(1) } + end + end + ensure + ActiveSupport::Notifications.unsubscribe subscriber + end + def test_cache_is_flat Task.cache do assert_queries(1) { Topic.find(1); Topic.find(1); } @@ -232,12 +327,62 @@ class QueryCacheTest < ActiveRecord::TestCase end end + def test_query_cache_does_not_establish_connection_if_unconnected + ActiveRecord::Base.clear_active_connections! + refute ActiveRecord::Base.connection_handler.active_connections? # sanity check + + middleware { + refute ActiveRecord::Base.connection_handler.active_connections?, "QueryCache forced ActiveRecord::Base to establish a connection in setup" + }.call({}) + + refute ActiveRecord::Base.connection_handler.active_connections?, "QueryCache forced ActiveRecord::Base to establish a connection in cleanup" + end + + def test_query_cache_is_enabled_on_connections_established_after_middleware_runs + ActiveRecord::Base.clear_active_connections! + refute ActiveRecord::Base.connection_handler.active_connections? # sanity check + + middleware { + assert ActiveRecord::Base.connection.query_cache_enabled, "QueryCache did not get lazily enabled" + }.call({}) + end + + def test_query_caching_is_local_to_the_current_thread + ActiveRecord::Base.clear_active_connections! + + middleware { + assert ActiveRecord::Base.connection_pool.query_cache_enabled + assert ActiveRecord::Base.connection.query_cache_enabled + + Thread.new { + refute ActiveRecord::Base.connection_pool.query_cache_enabled + refute ActiveRecord::Base.connection.query_cache_enabled + }.join + }.call({}) + end + private def middleware(&app) executor = Class.new(ActiveSupport::Executor) ActiveRecord::QueryCache.install_executor_hooks executor lambda { |env| executor.wrap { app.call(env) } } end + + def assert_cache(state, connection = ActiveRecord::Base.connection) + case state + when :off + assert !connection.query_cache_enabled, "cache should be off" + assert connection.query_cache.empty?, "cache should be empty" + when :clean + assert connection.query_cache_enabled, "cache should be on" + assert connection.query_cache.empty?, "cache should be empty" + when :dirty + assert connection.query_cache_enabled, "cache should be on" + assert !connection.query_cache.empty?, "cache should be dirty" + else + raise "unknown state" + end + end end class QueryCacheExpiryTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index 296dafacc2..05b71638c1 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -124,6 +124,10 @@ module ActiveRecord assert_equal "'lol'", @quoter.quote(DateTime.now, nil) end + def test_quoting_classes + assert_equal "'Object'", @quoter.quote(Object) + end + def test_crazy_object crazy = Object.new e = assert_raises(TypeError) do diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index 5dac3d064b..a90058e8bb 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -86,8 +86,8 @@ class ReflectionTest < ActiveRecord::TestCase column = @first.column_for_attribute("attribute_that_doesnt_exist") assert_instance_of ActiveRecord::ConnectionAdapters::NullColumn, column assert_equal "attribute_that_doesnt_exist", column.name - assert_equal nil, column.sql_type - assert_equal nil, column.type + assert_nil column.sql_type + assert_nil column.type end def test_non_existent_types_are_identity_types diff --git a/activerecord/test/cases/relation/or_test.rb b/activerecord/test/cases/relation/or_test.rb index 2796595523..abb7ca72dd 100644 --- a/activerecord/test/cases/relation/or_test.rb +++ b/activerecord/test/cases/relation/or_test.rb @@ -79,7 +79,7 @@ module ActiveRecord expected = Post.where("id = 1 or id = 2").to_a p = Post.where("id = 1") p.load - assert_equal p.loaded?, true + assert_equal true, p.loaded? assert_equal expected, p.or(Post.where("id = 2")).to_a end diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb index 925af49ffe..ed8ffddcf5 100644 --- a/activerecord/test/cases/relation/where_test.rb +++ b/activerecord/test/cases/relation/where_test.rb @@ -64,12 +64,12 @@ module ActiveRecord end def test_belongs_to_array_value_where - assert_equal Post.where(author_id: [1,2]).to_sql, Post.where(author: [1,2]).to_sql + assert_equal Post.where(author_id: [1, 2]).to_sql, Post.where(author: [1, 2]).to_sql end def test_belongs_to_nested_relation_where - expected = Post.where(author_id: Author.where(id: [1,2])).to_sql - actual = Post.where(author: Author.where(id: [1,2])).to_sql + expected = Post.where(author_id: Author.where(id: [1, 2])).to_sql + actual = Post.where(author: Author.where(id: [1, 2])).to_sql assert_equal expected, actual end @@ -87,7 +87,7 @@ module ActiveRecord def test_belongs_to_nested_where_with_relation author = authors(:david) - expected = Author.where(id: author ).joins(:posts) + expected = Author.where(id: author).joins(:posts) actual = Author.where(posts: { author_id: Author.where(id: author.id) }).joins(:posts) assert_equal expected.to_a, actual.to_a @@ -127,8 +127,8 @@ module ActiveRecord 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])) + 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])) assert_equal expected.to_sql, actual.to_sql end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 23d27ab90a..d5af0cc9a5 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -159,7 +159,7 @@ module ActiveRecord relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) relation = relation.merge where: { name: :lol }, readonly: true - assert_equal({ "name"=>:lol }, relation.where_clause.to_h) + assert_equal({ "name" => :lol }, relation.where_clause.to_h) assert_equal true, relation.readonly_value end @@ -224,7 +224,7 @@ module ActiveRecord def test_relation_merging_with_merged_joins_as_symbols special_comments_with_ratings = SpecialComment.joins(:ratings) posts_with_special_comments_with_ratings = Post.group("posts.id").joins(:special_comments).merge(special_comments_with_ratings) - assert_equal({ 2=>1, 4=>3, 5=>1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) + assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) end def test_relation_merging_with_joins_as_join_dependency_pick_proper_parent @@ -274,7 +274,7 @@ module ActiveRecord join_string = "LEFT OUTER JOIN #{Rating.quoted_table_name} ON #{SpecialComment.quoted_table_name}.id = #{Rating.quoted_table_name}.comment_id" special_comments_with_ratings = SpecialComment.joins join_string posts_with_special_comments_with_ratings = Post.group("posts.id").joins(:special_comments).merge(special_comments_with_ratings) - assert_equal({ 2=>1, 4=>3, 5=>1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) + assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) end class EnsureRoundTripTypeCasting < ActiveRecord::Type::Value diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 2e18c43b1b..981c2d758d 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -184,14 +184,14 @@ class RelationTest < ActiveRecord::TestCase def test_select_with_subquery_in_from_does_not_use_original_table_name relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type") - subquery = Comment.from(relation).select("type","post_count") - assert_equal(relation.map(&:post_count).sort,subquery.map(&:post_count).sort) + subquery = Comment.from(relation).select("type", "post_count") + assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort) end def test_group_with_subquery_in_from_does_not_use_original_table_name relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type") subquery = Comment.from(relation).group("type").average("post_count") - assert_equal(relation.map(&:post_count).sort,subquery.values.sort) + assert_equal(relation.map(&:post_count).sort, subquery.values.sort) end def test_finding_with_conditions @@ -291,7 +291,7 @@ class RelationTest < ActiveRecord::TestCase assert_includes Topic.order(id: "DESC").to_sql, "DESC" assert_includes Topic.order(id: "desc").to_sql, "DESC" assert_includes Topic.order(id: :DESC).to_sql, "DESC" - assert_includes Topic.order(id: :desc).to_sql,"DESC" + assert_includes Topic.order(id: :desc).to_sql, "DESC" end def test_raising_exception_on_invalid_hash_params @@ -365,7 +365,7 @@ class RelationTest < ActiveRecord::TestCase end def test_finding_with_sanitized_order - query = Tag.order(["field(id, ?)", [1,3,2]]).to_sql + 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 @@ -442,7 +442,7 @@ class RelationTest < ActiveRecord::TestCase assert_no_queries(ignore_none: false) do assert_equal 0, Developer.none.count assert_equal 0, Developer.none.calculate(:count, nil) - assert_equal nil, Developer.none.calculate(:average, "salary") + assert_nil Developer.none.calculate(:average, "salary") end end @@ -458,55 +458,55 @@ class RelationTest < ActiveRecord::TestCase def test_null_relation_sum ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:id).sum(:id) - assert_equal 0, ac.engines.count + assert_equal 0, ac.engines.count ac.save assert_equal Hash.new, ac.engines.group(:id).sum(:id) - assert_equal 0, ac.engines.count + assert_equal 0, ac.engines.count end def test_null_relation_count ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:id).count - assert_equal 0, ac.engines.count + assert_equal 0, ac.engines.count ac.save assert_equal Hash.new, ac.engines.group(:id).count - assert_equal 0, ac.engines.count + assert_equal 0, ac.engines.count end def test_null_relation_size ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:id).size - assert_equal 0, ac.engines.size + assert_equal 0, ac.engines.size ac.save assert_equal Hash.new, ac.engines.group(:id).size - assert_equal 0, ac.engines.size + assert_equal 0, ac.engines.size end def test_null_relation_average ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:car_id).average(:id) - assert_equal nil, ac.engines.average(:id) + assert_nil ac.engines.average(:id) ac.save assert_equal Hash.new, ac.engines.group(:car_id).average(:id) - assert_equal nil, ac.engines.average(:id) + assert_nil ac.engines.average(:id) end def test_null_relation_minimum ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id) - assert_equal nil, ac.engines.minimum(:id) + assert_nil ac.engines.minimum(:id) ac.save assert_equal Hash.new, ac.engines.group(:car_id).minimum(:id) - assert_equal nil, ac.engines.minimum(:id) + assert_nil ac.engines.minimum(:id) end def test_null_relation_maximum ac = Aircraft.new assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id) - assert_equal nil, ac.engines.maximum(:id) + assert_nil ac.engines.maximum(:id) ac.save assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id) - assert_equal nil, ac.engines.maximum(:id) + assert_nil ac.engines.maximum(:id) end def test_null_relation_in_where_condition @@ -785,7 +785,6 @@ class RelationTest < ActiveRecord::TestCase expected_taggings = taggings(:welcome_general, :thinking_general) assert_no_queries do - assert_equal expected_taggings, author.taggings.distinct.sort_by(&:id) assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id) end @@ -979,7 +978,7 @@ class RelationTest < ActiveRecord::TestCase assert ! davids.exists?(42) assert ! davids.exists?(davids.new.id) - fake = Author.where(name: "fake author") + fake = Author.where(name: "fake author") assert ! fake.exists? assert ! fake.exists?(authors(:david).id) end @@ -1815,7 +1814,7 @@ class RelationTest < ActiveRecord::TestCase end test "find_by returns nil if the record is missing" do - assert_equal nil, Post.all.find_by("1 = 0") + assert_nil Post.all.find_by("1 = 0") end test "find_by doesn't have implicit ordering" do @@ -1964,7 +1963,7 @@ class RelationTest < ActiveRecord::TestCase end def test_unscope_removes_binds - left = Post.where(id: Arel::Nodes::BindParam.new) + left = Post.where(id: Arel::Nodes::BindParam.new) column = Post.columns_hash["id"] left.bind_values += [[column, 20]] @@ -1973,8 +1972,8 @@ class RelationTest < ActiveRecord::TestCase end def test_merging_removes_rhs_bind_parameters - left = Post.where(id: 20) - right = Post.where(id: [1,2,3,4]) + left = Post.where(id: 20) + right = Post.where(id: [1, 2, 3, 4]) merged = left.merge(right) assert_equal [], merged.bind_values diff --git a/activerecord/test/cases/sanitize_test.rb b/activerecord/test/cases/sanitize_test.rb index 464bb12ccb..23bcb0af1e 100644 --- a/activerecord/test/cases/sanitize_test.rb +++ b/activerecord/test/cases/sanitize_test.rb @@ -12,8 +12,8 @@ class SanitizeTest < ActiveRecord::TestCase assert_equal "name='#{quoted_bambi}'", Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi"]) assert_equal "name='#{quoted_bambi}'", Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi".mb_chars]) quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote_string("Bambi\nand\nThumper") - assert_equal "name='#{quoted_bambi_and_thumper}'",Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi\nand\nThumper"]) - assert_equal "name='#{quoted_bambi_and_thumper}'",Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi\nand\nThumper".mb_chars]) + assert_equal "name='#{quoted_bambi_and_thumper}'", Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi\nand\nThumper"]) + assert_equal "name='#{quoted_bambi_and_thumper}'", Binary.send(:sanitize_sql_array, ["name='%s'", "Bambi\nand\nThumper".mb_chars]) end def test_sanitize_sql_array_handles_bind_variables diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index ae3a5651a1..bea78d2a95 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -148,12 +148,7 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{c_int_4.*limit: 4}, output end - if current_adapter?(:SQLite3Adapter) - assert_match %r{c_int_5.*limit: 5}, output - assert_match %r{c_int_6.*limit: 6}, output - assert_match %r{c_int_7.*limit: 7}, output - assert_match %r{c_int_8.*limit: 8}, output - elsif current_adapter?(:OracleAdapter) + if current_adapter?(:SQLite3Adapter, :OracleAdapter) assert_match %r{c_int_5.*limit: 5}, output assert_match %r{c_int_6.*limit: 6}, output assert_match %r{c_int_7.*limit: 7}, output @@ -346,7 +341,7 @@ class SchemaDumperTest < ActiveRecord::TestCase create_table("dogs") do |t| t.column :name, :string - t.column :owner_id, :integer + t.column :owner_id, :bigint t.index [:name] t.foreign_key :dog_owners, column: "owner_id" if supports_foreign_keys? end @@ -451,7 +446,7 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase def test_schema_dump_with_float_column_infinity_default skip unless current_adapter?(:PostgreSQLAdapter) - output = dump_table_schema('infinity_defaults') + output = dump_table_schema("infinity_defaults") assert_match %r{t\.float\s+"float_with_inf_default",\s+default: ::Float::INFINITY}, output assert_match %r{t\.float\s+"float_with_nan_default",\s+default: ::Float::NAN}, output end diff --git a/activerecord/test/cases/schema_loading_test.rb b/activerecord/test/cases/schema_loading_test.rb index 3d92a5e104..362370ac61 100644 --- a/activerecord/test/cases/schema_loading_test.rb +++ b/activerecord/test/cases/schema_loading_test.rb @@ -8,7 +8,7 @@ module SchemaLoadCounter def load_schema! self.load_schema_calls ||= 0 - self.load_schema_calls +=1 + self.load_schema_calls += 1 super end end diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb index 61062da3e1..b408a6000b 100644 --- a/activerecord/test/cases/scoping/default_scoping_test.rb +++ b/activerecord/test/cases/scoping/default_scoping_test.rb @@ -5,7 +5,6 @@ require "models/developer" require "models/computer" require "models/vehicle" require "models/cat" -require "active_support/core_ext/regexp" class DefaultScopingTest < ActiveRecord::TestCase fixtures :developers, :posts, :comments @@ -51,7 +50,7 @@ class DefaultScopingTest < ActiveRecord::TestCase def test_default_scope_with_conditions_string assert_equal Developer.where(name: "David").map(&:id).sort, DeveloperCalledDavid.all.map(&:id).sort - assert_equal nil, DeveloperCalledDavid.create!.name + assert_nil DeveloperCalledDavid.create!.name end def test_default_scope_with_conditions_hash @@ -315,7 +314,7 @@ class DefaultScopingTest < ActiveRecord::TestCase end def test_create_attribute_overwrites_default_values - assert_equal nil, PoorDeveloperCalledJamis.create!(salary: nil).salary + assert_nil PoorDeveloperCalledJamis.create!(salary: nil).salary assert_equal 50000, PoorDeveloperCalledJamis.create!(name: "David").salary end diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb index 58e1310ab0..995ff4dfc5 100644 --- a/activerecord/test/cases/scoping/named_scoping_test.rb +++ b/activerecord/test/cases/scoping/named_scoping_test.rb @@ -119,8 +119,8 @@ class NamedScopingTest < ActiveRecord::TestCase end def test_scope_with_STI - assert_equal 3,Post.containing_the_letter_a.count - assert_equal 1,SpecialPost.containing_the_letter_a.count + assert_equal 3, Post.containing_the_letter_a.count + assert_equal 1, SpecialPost.containing_the_letter_a.count end def test_has_many_through_associations_have_access_to_scopes diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb index 27b4583457..a1ae57fdbb 100644 --- a/activerecord/test/cases/scoping/relation_scoping_test.rb +++ b/activerecord/test/cases/scoping/relation_scoping_test.rb @@ -28,7 +28,7 @@ class RelationScopingTest < ActiveRecord::TestCase def test_scope_breaks_caching_on_collections author = authors :david ids = author.reload.special_posts_with_default_scope.map(&:id) - assert_equal [1,5,6], ids.sort + assert_equal [1, 5, 6], ids.sort scoped_posts = SpecialPostWithDefaultScope.unscoped do author = authors :david author.reload.special_posts_with_default_scope.to_a @@ -277,7 +277,7 @@ class NestedRelationScopingTest < ActiveRecord::TestCase assert_equal "David", Developer.first.name Developer.unscoped.where("name = 'Maiha'") do - assert_equal nil, Developer.first + assert_nil Developer.first end # ensure that scoping is restored diff --git a/activerecord/test/cases/secure_token_test.rb b/activerecord/test/cases/secure_token_test.rb index eda0229c26..7b9cbee40a 100644 --- a/activerecord/test/cases/secure_token_test.rb +++ b/activerecord/test/cases/secure_token_test.rb @@ -27,6 +27,6 @@ class SecureTokenTest < ActiveRecord::TestCase @user.token = "custom-secure-token" @user.save - assert_equal @user.token, "custom-secure-token" + assert_equal "custom-secure-token", @user.token end end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index 8e9514de7c..a469da0a5b 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -107,7 +107,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase end def test_serialized_time_attribute - myobj = Time.local(2008,1,1,1,0) + myobj = Time.local(2008, 1, 1, 1, 0) topic = Topic.create("content" => myobj).reload assert_equal(myobj, topic.content) end @@ -185,14 +185,14 @@ class SerializedAttributeTest < ActiveRecord::TestCase topic = Topic.new(content: true) assert topic.save topic = topic.reload - assert_equal topic.content, true + assert_equal true, topic.content end def test_serialized_boolean_value_false topic = Topic.new(content: false) assert topic.save topic = topic.reload - assert_equal topic.content, false + assert_equal false, topic.content end def test_serialize_with_coder @@ -211,7 +211,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase topic.save! topic.reload assert_kind_of some_class, topic.content - assert_equal topic.content, some_class.new("my value") + assert_equal some_class.new("my value"), topic.content end def test_serialize_attribute_via_select_method_when_time_zone_available @@ -313,8 +313,8 @@ class SerializedAttributeTest < ActiveRecord::TestCase return if value.nil? value.gsub(" encoded", "") end - type = Class.new(ActiveRecord::Type::Value) do - include ActiveRecord::Type::Helpers::Mutable + type = Class.new(ActiveModel::Type::Value) do + include ActiveModel::Type::Helpers::Mutable def serialize(value) return if value.nil? diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index d847a02679..d03231e711 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -24,7 +24,7 @@ module ActiveRecord sqlite3: :sqlite_tasks } - class DatabaseTasksUtilsTask< ActiveRecord::TestCase + class DatabaseTasksUtilsTask < ActiveRecord::TestCase def test_raises_an_error_when_called_with_protected_environment ActiveRecord::Migrator.stubs(:current_version).returns(1) diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index dbe935808e..285e718596 100644 --- a/activerecord/test/cases/tasks/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -59,7 +59,7 @@ if current_adapter?(:Mysql2Adapter) def test_when_database_created_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.create @configuration - assert_equal $stdout.string, "Created database 'my-app-db'\n" + assert_equal "Created database 'my-app-db'\n", $stdout.string end def test_create_when_database_exists_outputs_info_to_stderr @@ -69,7 +69,7 @@ if current_adapter?(:Mysql2Adapter) ActiveRecord::Tasks::DatabaseTasks.create @configuration - assert_equal $stderr.string, "Database 'my-app-db' already exists\n" + assert_equal "Database 'my-app-db' already exists\n", $stderr.string end end @@ -205,7 +205,7 @@ if current_adapter?(:Mysql2Adapter) def test_when_database_dropped_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.drop @configuration - assert_equal $stdout.string, "Dropped database 'my-app-db'\n" + assert_equal "Dropped database 'my-app-db'\n", $stdout.string end end diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index b8c8ec88f0..1a73d410d0 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -74,7 +74,7 @@ if current_adapter?(:PostgreSQLAdapter) def test_when_database_created_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.create @configuration - assert_equal $stdout.string, "Created database 'my-app-db'\n" + assert_equal "Created database 'my-app-db'\n", $stdout.string end def test_create_when_database_exists_outputs_info_to_stderr @@ -84,7 +84,7 @@ if current_adapter?(:PostgreSQLAdapter) ActiveRecord::Tasks::DatabaseTasks.create @configuration - assert_equal $stderr.string, "Database 'my-app-db' already exists\n" + assert_equal "Database 'my-app-db' already exists\n", $stderr.string end end @@ -126,7 +126,7 @@ if current_adapter?(:PostgreSQLAdapter) def test_when_database_dropped_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.drop @configuration - assert_equal $stdout.string, "Dropped database 'my-app-db'\n" + assert_equal "Dropped database 'my-app-db'\n", $stdout.string end end diff --git a/activerecord/test/cases/tasks/sqlite_rake_test.rb b/activerecord/test/cases/tasks/sqlite_rake_test.rb index 141048bfe7..0d917f3f6c 100644 --- a/activerecord/test/cases/tasks/sqlite_rake_test.rb +++ b/activerecord/test/cases/tasks/sqlite_rake_test.rb @@ -34,7 +34,7 @@ if current_adapter?(:SQLite3Adapter) def test_when_db_created_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root" - assert_equal $stdout.string, "Created database '#{@database}'\n" + assert_equal "Created database '#{@database}'\n", $stdout.string end def test_db_create_when_file_exists @@ -42,7 +42,7 @@ if current_adapter?(:SQLite3Adapter) ActiveRecord::Tasks::DatabaseTasks.create @configuration, "/rails/root" - assert_equal $stderr.string, "Database '#{@database}' already exists\n" + assert_equal "Database '#{@database}' already exists\n", $stderr.string end def test_db_create_with_file_does_nothing @@ -128,7 +128,7 @@ if current_adapter?(:SQLite3Adapter) def test_when_db_dropped_successfully_outputs_info_to_stdout ActiveRecord::Tasks::DatabaseTasks.drop @configuration, "/rails/root" - assert_equal $stdout.string, "Dropped database '#{@database}'\n" + assert_equal "Dropped database '#{@database}'\n", $stdout.string end end diff --git a/activerecord/test/cases/test_case.rb b/activerecord/test/cases/test_case.rb index 8eddc5a9ed..31b11c19f7 100644 --- a/activerecord/test/cases/test_case.rb +++ b/activerecord/test/cases/test_case.rb @@ -2,7 +2,6 @@ require "active_support/test_case" require "active_support/testing/autorun" require "active_support/testing/method_call_assertions" require "active_support/testing/stream" -require "active_support/core_ext/regexp" require "active_record/fixtures" require "cases/validations_repair_helper" @@ -64,11 +63,11 @@ module ActiveRecord assert_queries(0, options, &block) end - def assert_column(model, column_name, msg=nil) + def assert_column(model, column_name, msg = nil) assert has_column?(model, column_name), msg end - def assert_no_column(model, column_name, msg=nil) + def assert_no_column(model, column_name, msg = nil) assert_not has_column?(model, column_name), msg end diff --git a/activerecord/test/cases/test_fixtures_test.rb b/activerecord/test/cases/test_fixtures_test.rb index 14a5faa85e..7090202a89 100644 --- a/activerecord/test/cases/test_fixtures_test.rb +++ b/activerecord/test/cases/test_fixtures_test.rb @@ -3,7 +3,7 @@ require "cases/helper" class TestFixturesTest < ActiveRecord::TestCase setup do @klass = Class.new - @klass.send(:include, ActiveRecord::TestFixtures) + @klass.include(ActiveRecord::TestFixtures) end def test_deprecated_use_transactional_fixtures= diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index bd50fe55e9..391bbe8877 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -243,14 +243,14 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint - def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end - def @first.commits(i=0); @commits ||= 0; @commits += i if i; end + def @first.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end + def @first.commits(i = 0); @commits ||= 0; @commits += i if i; end @first.after_rollback_block { |r| r.rollbacks(1) } @first.after_commit_block { |r| r.commits(1) } second = TopicWithCallbacks.find(3) - def second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end - def second.commits(i=0); @commits ||= 0; @commits += i if i; end + def second.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end + def second.commits(i = 0); @commits ||= 0; @commits += i if i; end second.after_rollback_block { |r| r.rollbacks(1) } second.after_commit_block { |r| r.commits(1) } @@ -269,8 +269,8 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails - def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end - def @first.commits(i=0); @commits ||= 0; @commits += i if i; end + def @first.rollbacks(i = 0); @rollbacks ||= 0; @rollbacks += i if i; end + def @first.commits(i = 0); @commits ||= 0; @commits += i if i; end @first.after_rollback_block { |r| r.rollbacks(1) } @first.after_commit_block { |r| r.commits(1) } @@ -449,6 +449,51 @@ class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase end end +class CallbacksOnDestroyUpdateActionRaceTest < ActiveRecord::TestCase + class TopicWithHistory < ActiveRecord::Base + self.table_name = :topics + + def self.clear_history + @@history = [] + end + + def self.history + @@history ||= [] + end + end + + class TopicWithCallbacksOnDestroy < TopicWithHistory + after_commit(on: :destroy) { |record| record.class.history << :destroy } + end + + class TopicWithCallbacksOnUpdate < TopicWithHistory + after_commit(on: :update) { |record| record.class.history << :update } + end + + def test_trigger_once_on_multiple_deletions + TopicWithCallbacksOnDestroy.clear_history + topic = TopicWithCallbacksOnDestroy.new + topic.save + topic_clone = TopicWithCallbacksOnDestroy.find(topic.id) + topic.destroy + topic_clone.destroy + + assert_equal [:destroy], TopicWithCallbacksOnDestroy.history + end + + def test_trigger_on_update_where_row_was_deleted + TopicWithCallbacksOnUpdate.clear_history + topic = TopicWithCallbacksOnUpdate.new + topic.save + topic_clone = TopicWithCallbacksOnUpdate.find(topic.id) + topic.destroy + topic_clone.author_name = "Test Author" + topic_clone.save + + assert_equal [], TopicWithCallbacksOnUpdate.history + end +end + class TransactionEnrollmentCallbacksTest < ActiveRecord::TestCase class TopicWithoutTransactionalEnrollmentCallbacks < ActiveRecord::Base self.table_name = :topics diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 834365660f..9b1cca8583 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -98,7 +98,7 @@ class TransactionTest < ActiveRecord::TestCase end Topic.transaction do - @first.approved = true + @first.approved = true @first.save! end @@ -160,7 +160,7 @@ class TransactionTest < ActiveRecord::TestCase assert !@first.approved Topic.transaction do - @first.approved = true + @first.approved = true @first.save! end assert !Topic.find(@first.id).approved?, "Should not commit the approved flag" @@ -443,16 +443,16 @@ class TransactionTest < ActiveRecord::TestCase def test_using_named_savepoints Topic.transaction do - @first.approved = true + @first.approved = true @first.save! Topic.connection.create_savepoint("first") - @first.approved = false + @first.approved = false @first.save! Topic.connection.rollback_to_savepoint("first") assert @first.reload.approved? - @first.approved = false + @first.approved = false @first.save! Topic.connection.release_savepoint("first") assert_not @first.reload.approved? diff --git a/activerecord/test/cases/type/unsigned_integer_test.rb b/activerecord/test/cases/type/unsigned_integer_test.rb new file mode 100644 index 0000000000..1cd4dbc2c5 --- /dev/null +++ b/activerecord/test/cases/type/unsigned_integer_test.rb @@ -0,0 +1,17 @@ +require "cases/helper" + +module ActiveRecord + module Type + class UnsignedIntegerTest < ActiveRecord::TestCase + test "unsigned int max value is in range" do + assert_equal(4294967295, UnsignedInteger.new.serialize(4294967295)) + end + + test "minus value is out of range" do + assert_raises(ActiveModel::RangeError) do + UnsignedInteger.new.serialize(-1) + end + end + end + end +end diff --git a/activerecord/test/cases/validations/association_validation_test.rb b/activerecord/test/cases/validations/association_validation_test.rb index 66d6ecb928..f5ceb27d97 100644 --- a/activerecord/test/cases/validations/association_validation_test.rb +++ b/activerecord/test/cases/validations/association_validation_test.rb @@ -26,7 +26,7 @@ class AssociationValidationTest < ActiveRecord::TestCase def test_validates_associated_one Reply.validates :topic, associated: true - Topic.validates_presence_of( :content ) + Topic.validates_presence_of(:content) r = Reply.new("title" => "A reply", "content" => "with content!") r.topic = Topic.create("title" => "uhohuhoh") assert !r.valid? diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index 44b4e28777..6d22638592 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -6,6 +6,9 @@ require "models/guid" require "models/event" require "models/dashboard" require "models/uuid_item" +require "models/author" +require "models/person" +require "models/essay" class Wizard < ActiveRecord::Base self.abstract_class = true @@ -163,6 +166,19 @@ class UniquenessValidationTest < ActiveRecord::TestCase assert !r2.valid?, "Saving r2 first time" end + def test_validate_uniqueness_with_polymorphic_object_scope + Essay.validates_uniqueness_of(:name, scope: :writer) + + a = Author.create(name: "Sergey") + p = Person.create(first_name: "Sergey") + + e1 = a.essays.create(name: "Essay") + assert e1.valid?, "Saving e1" + + e2 = p.essays.create(name: "Essay") + assert e2.valid?, "Saving e2" + end + def test_validate_uniqueness_with_composed_attribute_scope r1 = ReplyWithTitleObject.create "title" => "r1", "content" => "hello world" assert r1.valid?, "Saving r1" diff --git a/activerecord/test/cases/view_test.rb b/activerecord/test/cases/view_test.rb index 0e38cee334..1f326d4b39 100644 --- a/activerecord/test/cases/view_test.rb +++ b/activerecord/test/cases/view_test.rb @@ -11,20 +11,21 @@ module ViewBehavior end class Ebook < ActiveRecord::Base + self.table_name = "ebooks'" self.primary_key = "id" end def setup super @connection = ActiveRecord::Base.connection - create_view "ebooks", <<-SQL + create_view "ebooks'", <<-SQL SELECT id, name, status FROM books WHERE format = 'ebook' SQL end def teardown super - drop_view "ebooks" + drop_view "ebooks'" end def test_reading @@ -66,15 +67,20 @@ module ViewBehavior def test_does_not_assume_id_column_as_primary_key model = Class.new(ActiveRecord::Base) do - self.table_name = "ebooks" + self.table_name = "ebooks'" end assert_nil model.primary_key end def test_does_not_dump_view_as_table - schema = dump_table_schema "ebooks" - assert_no_match %r{create_table "ebooks"}, schema + schema = dump_table_schema "ebooks'" + assert_no_match %r{create_table "ebooks'"}, schema end + + private + def quote_table_name(name) + @connection.quote_table_name(name) + end end if ActiveRecord::Base.connection.supports_views? @@ -83,11 +89,11 @@ if ActiveRecord::Base.connection.supports_views? private def create_view(name, query) - @connection.execute "CREATE VIEW #{name} AS #{query}" + @connection.execute "CREATE VIEW #{quote_table_name(name)} AS #{query}" end def drop_view(name) - @connection.execute "DROP VIEW #{name}" if @connection.view_exists? name + @connection.execute "DROP VIEW #{quote_table_name(name)}" if @connection.view_exists? name end end @@ -206,11 +212,11 @@ if ActiveRecord::Base.connection.respond_to?(:supports_materialized_views?) && private def create_view(name, query) - @connection.execute "CREATE MATERIALIZED VIEW #{name} AS #{query}" + @connection.execute "CREATE MATERIALIZED VIEW #{quote_table_name(name)} AS #{query}" end def drop_view(name) - @connection.execute "DROP MATERIALIZED VIEW #{name}" if @connection.view_exists? name + @connection.execute "DROP MATERIALIZED VIEW #{quote_table_name(name)}" if @connection.view_exists? name end end end diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 5192e5050a..1571b31329 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -95,7 +95,7 @@ class YamlSerializationTest < ActiveRecord::TestCase topic = YAML.load(yaml_fixture("rails_4_1")) assert topic.new_record? - assert_equal nil, topic.id + assert_nil topic.id assert_equal "The First Topic", topic.title assert_equal({ omg: :lol }, topic.content) end diff --git a/activerecord/test/config.example.yml b/activerecord/test/config.example.yml index 58e2d45748..4bcb2aeea6 100644 --- a/activerecord/test/config.example.yml +++ b/activerecord/test/config.example.yml @@ -77,6 +77,9 @@ connections: postgresql: arunit: min_messages: warning + arunit_without_prepared_statements: + min_messages: warning + prepared_statements: false arunit2: min_messages: warning diff --git a/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml b/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml new file mode 100644 index 0000000000..6f9da79b45 --- /dev/null +++ b/activerecord/test/fixtures/naked/yml/courses_with_invalid_key.yml @@ -0,0 +1,3 @@ +one: + id: 1 +two: ['not a hash'] diff --git a/activerecord/test/fixtures/other_dogs.yml b/activerecord/test/fixtures/other_dogs.yml new file mode 100644 index 0000000000..b576861929 --- /dev/null +++ b/activerecord/test/fixtures/other_dogs.yml @@ -0,0 +1,2 @@ +lassie: + id: 1 diff --git a/activerecord/test/models/admin/user.rb b/activerecord/test/models/admin/user.rb index 2e703f6219..a76e4b6795 100644 --- a/activerecord/test/models/admin/user.rb +++ b/activerecord/test/models/admin/user.rb @@ -22,11 +22,11 @@ class Admin::User < ActiveRecord::Base store :json_data_empty, accessors: [ :is_a_good_guy ], coder: Coder.new def phone_number - read_store_attribute(:settings, :phone_number).gsub(/(\d{3})(\d{3})(\d{4})/,'(\1) \2-\3') + read_store_attribute(:settings, :phone_number).gsub(/(\d{3})(\d{3})(\d{4})/, '(\1) \2-\3') end def phone_number=(value) - write_store_attribute(:settings, :phone_number, value && value.gsub(/[^\d]/,"")) + write_store_attribute(:settings, :phone_number, value && value.gsub(/[^\d]/, "")) end def color diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index 025630087c..4561b3132b 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -151,7 +151,7 @@ class Client < Company # is calling client.destroy, deleting from the database, or setting # foreign keys to NULL. def self.destroyed_client_ids - @destroyed_client_ids ||= Hash.new { |h,k| h[k] = [] } + @destroyed_client_ids ||= Hash.new { |h, k| h[k] = [] } end before_destroy do |client| @@ -199,7 +199,7 @@ class Account < ActiveRecord::Base alias_attribute :available_credit, :credit_limit def self.destroyed_account_ids - @destroyed_account_ids ||= Hash.new { |h,k| h[k] = [] } + @destroyed_account_ids ||= Hash.new { |h, k| h[k] = [] } end # Test private kernel method through collection proxy using has_many. diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index 682f99e365..0782c1eff4 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -88,7 +88,7 @@ module MyApplication validate :check_empty_credit_limit - protected + private def check_empty_credit_limit errors.add("credit_card", :blank) if credit_card.blank? diff --git a/activerecord/test/models/eye.rb b/activerecord/test/models/eye.rb index ab3b3eacf3..f53c34e4b1 100644 --- a/activerecord/test/models/eye.rb +++ b/activerecord/test/models/eye.rb @@ -22,12 +22,12 @@ class Eye < ActiveRecord::Base alias trace_after_create2 trace_after_create def trace_after_update - (@after_update_callbacks_stack ||= []) << iris.changed? + (@after_update_callbacks_stack ||= []) << iris.has_changes_to_save? end alias trace_after_update2 trace_after_update def trace_after_save - (@after_save_callbacks_stack ||= []) << iris.changed? + (@after_save_callbacks_stack ||= []) << iris.has_changes_to_save? end alias trace_after_save2 trace_after_save end diff --git a/activerecord/test/models/other_dog.rb b/activerecord/test/models/other_dog.rb new file mode 100644 index 0000000000..418caf34be --- /dev/null +++ b/activerecord/test/models/other_dog.rb @@ -0,0 +1,5 @@ +require_dependency "models/arunit2_model" + +class OtherDog < ARUnit2Model + self.table_name = "dogs" +end diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index 2dc8f9bd84..c532ab426e 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -9,10 +9,10 @@ class Pirate < ActiveRecord::Base before_remove: :log_before_remove, after_remove: :log_after_remove has_and_belongs_to_many :parrots_with_proc_callbacks, class_name: "Parrot", - before_add: proc { |p,pa| p.ship_log << "before_adding_proc_parrot_#{pa.id || '<new>'}" }, - after_add: proc { |p,pa| p.ship_log << "after_adding_proc_parrot_#{pa.id || '<new>'}" }, - before_remove: proc { |p,pa| p.ship_log << "before_removing_proc_parrot_#{pa.id}" }, - after_remove: proc { |p,pa| p.ship_log << "after_removing_proc_parrot_#{pa.id}" } + before_add: proc { |p, pa| p.ship_log << "before_adding_proc_parrot_#{pa.id || '<new>'}" }, + after_add: proc { |p, pa| p.ship_log << "after_adding_proc_parrot_#{pa.id || '<new>'}" }, + before_remove: proc { |p, pa| p.ship_log << "before_removing_proc_parrot_#{pa.id}" }, + after_remove: proc { |p, pa| p.ship_log << "after_removing_proc_parrot_#{pa.id}" } has_and_belongs_to_many :autosaved_parrots, class_name: "Parrot", autosave: true has_many :treasures, as: :looter @@ -28,10 +28,10 @@ class Pirate < ActiveRecord::Base before_remove: :log_before_remove, after_remove: :log_after_remove has_many :birds_with_proc_callbacks, class_name: "Bird", - before_add: proc { |p,b| p.ship_log << "before_adding_proc_bird_#{b.id || '<new>'}" }, - after_add: proc { |p,b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}" }, - before_remove: proc { |p,b| p.ship_log << "before_removing_proc_bird_#{b.id}" }, - after_remove: proc { |p,b| p.ship_log << "after_removing_proc_bird_#{b.id}" } + before_add: proc { |p, b| p.ship_log << "before_adding_proc_bird_#{b.id || '<new>'}" }, + after_add: proc { |p, b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}" }, + before_remove: proc { |p, b| p.ship_log << "before_removing_proc_bird_#{b.id}" }, + after_remove: proc { |p, b| p.ship_log << "after_removing_proc_bird_#{b.id}" } has_many :birds_with_reject_all_blank, class_name: "Bird" has_one :foo_bulb, -> { where name: "foo" }, foreign_key: :car_id, class_name: "Bulb" diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 66a99cbcda..e74aedb814 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -47,7 +47,7 @@ class Post < ActiveRecord::Base scope :typographically_interesting, -> { containing_the_letter_a.or(titled_with_an_apostrophe) } - has_many :comments do + has_many :comments do def find_most_recent order("id DESC").first end @@ -168,7 +168,7 @@ class Post < ActiveRecord::Base @log = [] end - def self.log(message=nil, side=nil, new_record=nil) + def self.log(message = nil, side = nil, new_record = nil) return @log if message.nil? @log << [message, side, new_record] end @@ -231,7 +231,7 @@ end class SpecialPostWithDefaultScope < ActiveRecord::Base self.inheritance_column = :disabled self.table_name = "posts" - default_scope { where(id: [1, 5,6]) } + default_scope { where(id: [1, 5, 6]) } end class PostThatLoadsCommentsInAnAfterSaveHook < ActiveRecord::Base diff --git a/activerecord/test/models/subject.rb b/activerecord/test/models/subject.rb index 29e290825e..504f68a296 100644 --- a/activerecord/test/models/subject.rb +++ b/activerecord/test/models/subject.rb @@ -5,7 +5,7 @@ class Subject < ActiveRecord::Base # as otherwise synonym test was failing after_initialize :set_email_address - protected + private def set_email_address unless persisted? self.author_email_address = "test@test.com" diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index db04735d01..0420e2d15c 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -73,7 +73,7 @@ class Topic < ActiveRecord::Base write_attribute(:approved, val) end - protected + private def default_written_on self.written_on = Time.now unless attribute_present?("written_on") diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb index f00b858ea6..15ba2d67ab 100644 --- a/activerecord/test/schema/postgresql_specific_schema.rb +++ b/activerecord/test/schema/postgresql_specific_schema.rb @@ -1,6 +1,7 @@ ActiveRecord::Schema.define do enable_extension!("uuid-ossp", ActiveRecord::Base.connection) + enable_extension!("pgcrypto", ActiveRecord::Base.connection) if ActiveRecord::Base.connection.supports_pgcrypto_uuid? create_table :uuid_parents, id: :uuid, force: true do |t| t.string :name diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index d2fb090118..9d76d0537e 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -54,7 +54,7 @@ ActiveRecord::Schema.define do create_table :authors, force: true do |t| t.string :name, null: false - t.integer :author_address_id + t.bigint :author_address_id t.integer :author_address_extra_id t.string :organization_id t.string :owned_essay_id @@ -126,6 +126,9 @@ ActiveRecord::Schema.define do t.timestamps null: false end + create_table :old_cars, id: :integer, force: true do |t| + end + create_table :carriers, force: true create_table :categories, force: true do |t| @@ -303,7 +306,7 @@ ActiveRecord::Schema.define do end create_table :engines, force: true do |t| - t.integer :car_id + t.bigint :car_id end create_table :entrants, force: true do |t| @@ -436,10 +439,12 @@ ActiveRecord::Schema.define do end create_table :lock_without_defaults, force: true do |t| + t.column :title, :string t.column :lock_version, :integer end create_table :lock_without_defaults_cust, force: true do |t| + t.column :title, :string t.column :custom_lock_version, :integer end @@ -903,7 +908,6 @@ ActiveRecord::Schema.define do create_table(t, force: true) {} end - # NOTE - the following 4 tables are used by models that have :inverse_of options on the associations create_table :men, force: true do |t| t.string :name end @@ -927,14 +931,14 @@ ActiveRecord::Schema.define do t.integer :zine_id end - create_table :wheels, force: true do |t| - t.references :wheelable, polymorphic: true - end - create_table :zines, force: true do |t| t.string :title end + create_table :wheels, force: true do |t| + t.references :wheelable, polymorphic: true + end + create_table :countries, force: true, id: false, primary_key: "country_id" do |t| t.string :country_id t.string :name @@ -1003,7 +1007,7 @@ ActiveRecord::Schema.define do if supports_foreign_keys? # fk_test_has_fk should be before fk_test_has_pk create_table :fk_test_has_fk, force: true do |t| - t.integer :fk_id, null: false + t.bigint :fk_id, null: false end create_table :fk_test_has_pk, force: true, primary_key: "pk_id" do |t| @@ -1046,3 +1050,5 @@ Professor.connection.create_table :courses_professors, id: false, force: true do t.references :course t.references :professor end + +OtherDog.connection.create_table :dogs, force: true diff --git a/activerecord/test/support/config.rb b/activerecord/test/support/config.rb index d0717f7b34..aaff408b41 100644 --- a/activerecord/test/support/config.rb +++ b/activerecord/test/support/config.rb @@ -1,5 +1,5 @@ require "yaml" -require "erubis" +require "erb" require "fileutils" require "pathname" @@ -20,13 +20,14 @@ module ARTest FileUtils.cp TEST_ROOT + "/config.example.yml", config_file end - erb = Erubis::Eruby.new(config_file.read) + erb = ERB.new(config_file.read) expand_config(YAML.parse(erb.result(binding)).transform) end def expand_config(config) config["connections"].each do |adapter, connection| - dbs = [["arunit", "activerecord_unittest"], ["arunit2", "activerecord_unittest2"]] + dbs = [["arunit", "activerecord_unittest"], ["arunit2", "activerecord_unittest2"], + ["arunit_without_prepared_statements", "activerecord_unittest"]] dbs.each do |name, dbname| unless connection[name].is_a?(Hash) connection[name] = { "database" => connection[name] } diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb index c9260398e2..bc5af36a28 100644 --- a/activerecord/test/support/connection.rb +++ b/activerecord/test/support/connection.rb @@ -2,6 +2,7 @@ require "active_support/logger" require "models/college" require "models/course" require "models/professor" +require "models/other_dog" module ARTest def self.connection_name |