diff options
Diffstat (limited to 'activerecord/test')
29 files changed, 533 insertions, 283 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index a1fb6427f9..827bcba121 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -211,6 +211,28 @@ module ActiveRecord end end + def test_exceptions_from_notifications_are_not_translated + original_error = StandardError.new("This StandardError shouldn't get translated") + subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") { raise original_error } + actual_error = assert_raises(StandardError) do + @connection.execute("SELECT * FROM posts") + end + + assert_equal original_error, actual_error + + ensure + ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber + end + + def test_database_related_exceptions_are_translated_to_statement_invalid + error = assert_raises(ActiveRecord::StatementInvalid) do + @connection.execute("This is a syntax error") + end + + assert_instance_of ActiveRecord::StatementInvalid, error + assert_kind_of Exception, error.cause + end + def test_select_all_always_return_activerecord_result result = @connection.select_all "SELECT * FROM posts" assert result.is_a?(ActiveRecord::Result) diff --git a/activerecord/test/cases/adapters/mysql2/virtual_column_test.rb b/activerecord/test/cases/adapters/mysql2/virtual_column_test.rb index 442a4fb7b5..1c5ef2aa41 100644 --- a/activerecord/test/cases/adapters/mysql2/virtual_column_test.rb +++ b/activerecord/test/cases/adapters/mysql2/virtual_column_test.rb @@ -52,7 +52,7 @@ if ActiveRecord::Base.connection.supports_virtual_columns? def test_schema_dumping output = dump_table_schema("virtual_columns") - assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "UPPER\(`name`\)"$/i, output) + assert_match(/t\.virtual\s+"upper_name",\s+type: :string,\s+as: "(?:UPPER|UCASE)\(`name`\)"$/i, output) assert_match(/t\.virtual\s+"name_length",\s+type: :integer,\s+as: "LENGTH\(`name`\)",\s+stored: true$/i, output) end end diff --git a/activerecord/test/cases/adapters/postgresql/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index a1e966b915..d7b23ad41d 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -9,11 +9,11 @@ module ActiveRecord end def test_type_cast_true - assert_equal "t", @conn.type_cast(true) + assert_equal true, @conn.type_cast(true) end def test_type_cast_false - assert_equal "f", @conn.type_cast(false) + assert_equal false, @conn.type_cast(false) end def test_quote_float_nan diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 8eddd81c38..00de92cdfd 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -124,7 +124,9 @@ class PostgresqlUUIDTest < ActiveRecord::PostgreSQLTestCase "Z0000C99-9C0B-4EF8-BB6D-6BB9BD380A11", "a0eebc999r0b4ef8ab6d6bb9bd380a11", "a0ee-bc99------4ef8-bb6d-6bb9-bd38-0a11", - "{a0eebc99-bb6d6bb9-bd380a11}"].each do |invalid_uuid| + "{a0eebc99-bb6d6bb9-bd380a11}", + "{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11", + "a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}"].each do |invalid_uuid| uuid = UUIDType.new guid: invalid_uuid assert_nil uuid.guid end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb index aefbb309e6..815453ad50 100644 --- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -5,6 +5,11 @@ require "securerandom" class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase def setup @conn = ActiveRecord::Base.connection + @initial_represent_boolean_as_integer = ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer + end + + def teardown + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = @initial_represent_boolean_as_integer end def test_type_cast_binary_encoding_without_logger @@ -15,11 +20,19 @@ class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase end def test_type_cast_true + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false assert_equal "t", @conn.type_cast(true) + + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true + assert_equal 1, @conn.type_cast(true) end def test_type_cast_false + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false assert_equal "f", @conn.type_cast(false) + + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true + assert_equal 0, @conn.type_cast(false) end def test_type_cast_bigdecimal diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index a727cc6e60..a7ac291f23 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -647,8 +647,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase def test_new_record_with_foreign_key_but_no_object client = Client.new("firm_id" => 1) - # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first - assert_equal Firm.all.merge!(order: "id").first, client.firm_with_basic_id + assert_equal Firm.first, client.firm_with_basic_id end def test_setting_foreign_key_after_nil_target_loaded diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index a7e16af88d..2682f256ff 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -497,21 +497,20 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_predicate person.references, :exists? end - # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first def test_counting_with_counter_sql - assert_equal 3, Firm.all.merge!(order: "id").first.clients.count + assert_equal 3, Firm.first.clients.count end def test_counting - assert_equal 3, Firm.all.merge!(order: "id").first.plain_clients.count + assert_equal 3, Firm.first.plain_clients.count end def test_counting_with_single_hash - assert_equal 1, Firm.all.merge!(order: "id").first.plain_clients.where(name: "Microsoft").count + assert_equal 1, Firm.first.plain_clients.where(name: "Microsoft").count end def test_counting_with_column_name_and_hash - assert_equal 3, Firm.all.merge!(order: "id").first.plain_clients.count(:name) + assert_equal 3, Firm.first.plain_clients.count(:name) end def test_counting_with_association_limit @@ -521,7 +520,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_finding - assert_equal 3, Firm.all.merge!(order: "id").first.clients.length + assert_equal 3, Firm.first.clients.length end def test_finding_array_compatibility @@ -593,27 +592,27 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_finding_default_orders - assert_equal "Summit", Firm.all.merge!(order: "id").first.clients.first.name + assert_equal "Summit", Firm.first.clients.first.name end def test_finding_with_different_class_name_and_order - assert_equal "Apex", Firm.all.merge!(order: "id").first.clients_sorted_desc.first.name + assert_equal "Apex", Firm.first.clients_sorted_desc.first.name end def test_finding_with_foreign_key - assert_equal "Microsoft", Firm.all.merge!(order: "id").first.clients_of_firm.first.name + assert_equal "Microsoft", Firm.first.clients_of_firm.first.name end def test_finding_with_condition - assert_equal "Microsoft", Firm.all.merge!(order: "id").first.clients_like_ms.first.name + assert_equal "Microsoft", Firm.first.clients_like_ms.first.name end def test_finding_with_condition_hash - assert_equal "Microsoft", Firm.all.merge!(order: "id").first.clients_like_ms_with_hash_conditions.first.name + assert_equal "Microsoft", Firm.first.clients_like_ms_with_hash_conditions.first.name end def test_finding_using_primary_key - assert_equal "Summit", Firm.all.merge!(order: "id").first.clients_using_primary_key.first.name + assert_equal "Summit", Firm.first.clients_using_primary_key.first.name end def test_update_all_on_association_accessed_before_save @@ -636,7 +635,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_ids - firm = Firm.all.merge!(order: "id").first + firm = Firm.first assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find } @@ -656,7 +655,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_one_message_on_primary_key - firm = Firm.all.merge!(order: "id").first + firm = Firm.first e = assert_raises(ActiveRecord::RecordNotFound) do firm.clients.find(0) @@ -682,7 +681,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_all - firm = Firm.all.merge!(order: "id").first + firm = Firm.first assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length end @@ -727,29 +726,28 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_all_sanitized - # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first - firm = Firm.all.merge!(order: "id").first + firm = Firm.first summit = firm.clients.where("name = 'Summit'").to_a assert_equal summit, firm.clients.where("name = ?", "Summit").to_a assert_equal summit, firm.clients.where("name = :name", name: "Summit").to_a end def test_find_first - firm = Firm.all.merge!(order: "id").first + firm = Firm.first client2 = Client.find(2) assert_equal firm.clients.first, firm.clients.order("id").first assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first end def test_find_first_sanitized - firm = Firm.all.merge!(order: "id").first + firm = Firm.first client2 = Client.find(2) - assert_equal client2, firm.clients.merge!(where: ["#{QUOTED_TYPE} = ?", "Client"], order: "id").first - assert_equal client2, firm.clients.merge!(where: ["#{QUOTED_TYPE} = :type", { type: "Client" }], order: "id").first + assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = ?", "Client").first + assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = :type", type: "Client").first end def test_find_first_after_reset_scope - firm = Firm.all.merge!(order: "id").first + firm = Firm.first collection = firm.clients original_object = collection.first @@ -760,7 +758,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_first_after_reset - firm = Firm.all.merge!(order: "id").first + firm = Firm.first collection = firm.clients original_object = collection.first @@ -772,7 +770,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_find_first_after_reload - firm = Firm.all.merge!(order: "id").first + firm = Firm.first collection = firm.clients original_object = collection.first @@ -875,7 +873,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_create_with_bang_on_has_many_raises_when_record_not_saved assert_raise(ActiveRecord::RecordInvalid) do - firm = Firm.all.merge!(order: "id").first + firm = Firm.first firm.plain_clients.create! end end @@ -1557,8 +1555,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_destroy_dependent_when_deleted_from_association - # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first - firm = Firm.all.merge!(order: "id").first + firm = Firm.first assert_equal 3, firm.clients.size client = firm.clients.first @@ -1668,7 +1665,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_replace_with_less - firm = Firm.all.merge!(order: "id").first + firm = Firm.first firm.clients = [companies(:first_client)] assert firm.save, "Could not save firm" firm.reload @@ -1682,7 +1679,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_replace_with_new - firm = Firm.all.merge!(order: "id").first + firm = Firm.first firm.clients = [companies(:second_client), Client.new("name" => "New Client")] firm.save firm.reload @@ -2080,7 +2077,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_creating_using_primary_key - firm = Firm.all.merge!(order: "id").first + firm = Firm.first client = firm.clients_using_primary_key.create!(name: "test") assert_equal firm.name, client.firm_name end 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 1c2138a3d0..a76159fb99 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -946,6 +946,13 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end end + def test_has_many_through_polymorphic_with_rewhere + post = TaggedPost.create!(title: "Tagged", body: "Post") + tag = post.tags.create!(name: "Tag") + assert_equal [tag], TaggedPost.preload(:tags).last.tags + assert_equal [tag], TaggedPost.eager_load(:tags).last.tags + end + def test_has_many_through_polymorphic_with_primary_key_option assert_equal [categories(:general)], authors(:david).essay_categories diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index 1fc63a49d4..934d5bf8b2 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -8,11 +8,10 @@ module ActiveRecord end def setup - @klass = Class.new do + @klass = Class.new(Class.new { def self.initialize_generated_modules; end }) do def self.superclass; Base; end def self.base_class; self; end def self.decorate_matching_attribute_types(*); end - def self.initialize_generated_modules; end include ActiveRecord::DefineCallbacks include ActiveRecord::AttributeMethods diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 4d24a980dc..366577761c 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -1005,7 +1005,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase class_eval(&block) end - assert_empty klass.generated_attribute_methods.instance_methods(false) + assert_empty klass.send(:generated_attribute_methods).instance_methods(false) klass end diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index 1a66b82b2e..dcd3af487b 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require "models/comment" require "models/post" require "models/subscriber" @@ -610,4 +611,64 @@ class EachTest < ActiveRecord::TestCase end assert_equal expected, actual end + + test ".find_each bypasses the query cache for its own queries" do + Post.cache do + assert_queries(2) do + Post.find_each {} + Post.find_each {} + end + end + end + + test ".find_each does not disable the query cache inside the given block" do + Post.cache do + Post.find_each(start: 1, finish: 1) do |post| + assert_queries(1) do + post.comments.count + post.comments.count + end + end + end + end + + test ".find_in_batches bypasses the query cache for its own queries" do + Post.cache do + assert_queries(2) do + Post.find_in_batches {} + Post.find_in_batches {} + end + end + end + + test ".find_in_batches does not disable the query cache inside the given block" do + Post.cache do + Post.find_in_batches(start: 1, finish: 1) do |batch| + assert_queries(1) do + batch.first.comments.count + batch.first.comments.count + end + end + end + end + + test ".in_batches bypasses the query cache for its own queries" do + Post.cache do + assert_queries(2) do + Post.in_batches {} + Post.in_batches {} + end + end + end + + test ".in_batches does not disable the query cache inside the given block" do + Post.cache do + Post.in_batches(start: 1, finish: 1) do |relation| + assert_queries(1) do + relation.count + relation.count + end + end + end + end end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 80baaac30a..7d6dc21e34 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -817,4 +817,46 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal 6, Account.sum(:firm_id) { 1 } end end + + test "#skip_query_cache! for #pluck" do + Account.cache do + assert_queries(1) do + Account.pluck(:credit_limit) + Account.pluck(:credit_limit) + end + + assert_queries(2) do + Account.all.skip_query_cache!.pluck(:credit_limit) + Account.all.skip_query_cache!.pluck(:credit_limit) + end + end + end + + test "#skip_query_cache! for a simple calculation" do + Account.cache do + assert_queries(1) do + Account.calculate(:sum, :credit_limit) + Account.calculate(:sum, :credit_limit) + end + + assert_queries(2) do + Account.all.skip_query_cache!.calculate(:sum, :credit_limit) + Account.all.skip_query_cache!.calculate(:sum, :credit_limit) + end + end + end + + test "#skip_query_cache! for a grouped calculation" do + Account.cache do + assert_queries(1) do + Account.group(:firm_id).calculate(:sum, :credit_limit) + Account.group(:firm_id).calculate(:sum, :credit_limit) + end + + assert_queries(2) do + Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit) + Account.all.skip_query_cache!.group(:firm_id).calculate(:sum, :credit_limit) + end + end + end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index f72e0d2ead..bb584b0c6f 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -299,11 +299,9 @@ class DirtyTest < ActiveRecord::TestCase end def test_virtual_attribute_will_change - assert_deprecated do - parrot = Parrot.create!(name: "Ruby") - parrot.send(:attribute_will_change!, :cancel_save_from_callback) - assert parrot.has_changes_to_save? - end + parrot = Parrot.create!(name: "Ruby") + parrot.send(:attribute_will_change!, :cancel_save_from_callback) + assert parrot.has_changes_to_save? end def test_association_assignment_changes_foreign_key @@ -839,15 +837,14 @@ class DirtyTest < ActiveRecord::TestCase 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 + test "changed? in after callbacks returns false" 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 "changed? should be false" if changed? raise "has_changes_to_save? should be false" if has_changes_to_save? + raise "saved_changes? should be true" unless saved_changes? end end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 420f552ef6..af21cd529f 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -1232,6 +1232,34 @@ class FinderTest < ActiveRecord::TestCase assert_equal tyre2, zyke.tyres.custom_find_by(id: tyre2.id) end + test "#skip_query_cache! for #exists?" do + Topic.cache do + assert_queries(1) do + Topic.exists? + Topic.exists? + end + + assert_queries(2) do + Topic.all.skip_query_cache!.exists? + Topic.all.skip_query_cache!.exists? + end + end + end + + test "#skip_query_cache! for #exists? with a limited eager load" do + Topic.cache do + assert_queries(2) do + Topic.eager_load(:replies).limit(1).exists? + Topic.eager_load(:replies).limit(1).exists? + end + + assert_queries(4) do + Topic.eager_load(:replies).limit(1).skip_query_cache!.exists? + Topic.eager_load(:replies).limit(1).skip_query_cache!.exists? + end + end + end + private def table_with_custom_primary_key yield(Class.new(Toy) do diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index 9b4b61b16e..a6ea27bf48 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -160,10 +160,8 @@ class JsonSerializationTest < ActiveRecord::TestCase end def test_serializable_hash_should_not_modify_options_in_argument - options = { only: :name } - @contact.serializable_hash(options) - - assert_nil options[:except] + options = { only: :name }.freeze + assert_nothing_raised { @contact.serializable_hash(options) } end end diff --git a/activerecord/test/cases/multiparameter_attributes_test.rb b/activerecord/test/cases/multiparameter_attributes_test.rb index ceb5724377..aa521e907c 100644 --- a/activerecord/test/cases/multiparameter_attributes_test.rb +++ b/activerecord/test/cases/multiparameter_attributes_test.rb @@ -271,6 +271,12 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase ensure Topic.reset_column_information end + + def test_multiparameter_attributes_setting_time_attribute + 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_on_time_with_empty_seconds @@ -285,14 +291,6 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase end end - unless current_adapter? :OracleAdapter - def test_multiparameter_attributes_setting_time_attribute - 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") assert_equal 1952, topic.written_on.year @@ -300,13 +298,34 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase assert_equal 11, topic.written_on.day end + def test_create_with_multiparameter_attributes_setting_date_attribute + topic = Topic.create_with("written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11").new + assert_equal 1952, topic.written_on.year + assert_equal 3, topic.written_on.month + assert_equal 11, topic.written_on.day + end + def test_multiparameter_attributes_setting_date_and_time_attribute topic = Topic.new( - "written_on(1i)" => "1952", - "written_on(2i)" => "3", - "written_on(3i)" => "11", - "written_on(4i)" => "13", - "written_on(5i)" => "55") + "written_on(1i)" => "1952", + "written_on(2i)" => "3", + "written_on(3i)" => "11", + "written_on(4i)" => "13", + "written_on(5i)" => "55") + assert_equal 1952, topic.written_on.year + assert_equal 3, topic.written_on.month + assert_equal 11, topic.written_on.day + assert_equal 13, topic.written_on.hour + assert_equal 55, topic.written_on.min + end + + def test_create_with_multiparameter_attributes_setting_date_and_time_attribute + topic = Topic.create_with( + "written_on(1i)" => "1952", + "written_on(2i)" => "3", + "written_on(3i)" => "11", + "written_on(4i)" => "13", + "written_on(5i)" => "55").new assert_equal 1952, topic.written_on.year assert_equal 3, topic.written_on.month assert_equal 11, topic.written_on.day @@ -364,4 +383,15 @@ class MultiParameterAttributeTest < ActiveRecord::TestCase assert_equal("address", ex.errors[0].attribute) end + + def test_multiparameter_assigned_attributes_did_not_come_from_user + topic = Topic.new( + "written_on(1i)" => "1952", + "written_on(2i)" => "3", + "written_on(3i)" => "11", + "written_on(4i)" => "13", + "written_on(5i)" => "55", + ) + refute_predicate topic, :written_on_came_from_user? + end end diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb index e3bb51bd77..4e3daeabb6 100644 --- a/activerecord/test/cases/multiple_db_test.rb +++ b/activerecord/test/cases/multiple_db_test.rb @@ -90,14 +90,9 @@ class MultipleDbTest < ActiveRecord::TestCase assert_equal "Ruby Developer", Entrant.find(1).name end - def test_arel_table_engines - assert_not_equal Entrant.arel_engine, Bird.arel_engine - assert_not_equal Entrant.arel_engine, Course.arel_engine - end - def test_connection - assert_equal Entrant.arel_engine.connection.object_id, Bird.arel_engine.connection.object_id - assert_not_equal Entrant.arel_engine.connection.object_id, Course.arel_engine.connection.object_id + assert_same Entrant.connection, Bird.connection + assert_not_same Entrant.connection, Course.connection end unless in_memory_db? diff --git a/activerecord/test/cases/null_relation_test.rb b/activerecord/test/cases/null_relation_test.rb new file mode 100644 index 0000000000..56f5a89686 --- /dev/null +++ b/activerecord/test/cases/null_relation_test.rb @@ -0,0 +1,82 @@ +require "cases/helper" +require "models/developer" +require "models/comment" +require "models/post" +require "models/topic" + +class NullRelationTest < ActiveRecord::TestCase + fixtures :posts, :comments + + def test_none + assert_no_queries(ignore_none: false) do + assert_equal [], Developer.none + assert_equal [], Developer.all.none + end + end + + def test_none_chainable + assert_no_queries(ignore_none: false) do + assert_equal [], Developer.none.where(name: "David") + end + end + + def test_none_chainable_to_existing_scope_extension_method + assert_no_queries(ignore_none: false) do + assert_equal 1, Topic.anonymous_extension.none.one + end + end + + def test_none_chained_to_methods_firing_queries_straight_to_db + assert_no_queries(ignore_none: false) do + assert_equal [], Developer.none.pluck(:id, :name) + assert_equal 0, Developer.none.delete_all + assert_equal 0, Developer.none.update_all(name: "David") + assert_equal 0, Developer.none.delete(1) + assert_equal false, Developer.none.exists?(1) + end + end + + def test_null_relation_content_size_methods + assert_no_queries(ignore_none: false) do + assert_equal 0, Developer.none.size + assert_equal 0, Developer.none.count + assert_equal true, Developer.none.empty? + assert_equal true, Developer.none.none? + assert_equal false, Developer.none.any? + assert_equal false, Developer.none.one? + assert_equal false, Developer.none.many? + end + end + + def test_null_relation_metadata_methods + assert_equal "", Developer.none.to_sql + assert_equal({}, Developer.none.where_values_hash) + end + + def test_null_relation_where_values_hash + assert_equal({ "salary" => 100_000 }, Developer.none.where(salary: 100_000).where_values_hash) + end + + [:count, :sum].each do |method| + define_method "test_null_relation_#{method}" do + assert_no_queries(ignore_none: false) do + assert_equal 0, Comment.none.public_send(method, :id) + assert_equal Hash.new, Comment.none.group(:post_id).public_send(method, :id) + end + end + end + + [:average, :minimum, :maximum].each do |method| + define_method "test_null_relation_#{method}" do + assert_no_queries(ignore_none: false) do + assert_nil Comment.none.public_send(method, :id) + assert_equal Hash.new, Comment.none.group(:post_id).public_send(method, :id) + end + end + end + + def test_null_relation_in_where_condition + assert_operator Comment.count, :>, 0 # precondition, make sure there are comments. + assert_equal 0, Comment.where(post_id: Post.none).count + end +end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 5895c51714..5830f9916a 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -437,6 +437,13 @@ class PersistenceTest < ActiveRecord::TestCase assert_not_nil Topic.find(2) end + def test_delete_isnt_affected_by_scoping + topic = Topic.find(1) + assert_difference("Topic.count", -1) do + Topic.where("1=0").scoping { topic.delete } + end + end + def test_destroy topic = Topic.find(1) assert_equal topic, topic.destroy, "topic.destroy did not return self" diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index 0819776fbf..98b20915c6 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -8,11 +8,11 @@ module ActiveRecord end def test_quoted_true - assert_equal "'t'", @quoter.quoted_true + assert_equal "TRUE", @quoter.quoted_true end def test_quoted_false - assert_equal "'f'", @quoter.quoted_false + assert_equal "FALSE", @quoter.quoted_false end def test_quote_column_name @@ -174,13 +174,21 @@ module ActiveRecord def test_type_cast_date date = Date.today - expected = @conn.quoted_date(date) + if current_adapter?(:Mysql2Adapter) + expected = date + else + expected = @conn.quoted_date(date) + end assert_equal expected, @conn.type_cast(date) end def test_type_cast_time time = Time.now - expected = @conn.quoted_date(time) + if current_adapter?(:Mysql2Adapter) + expected = time + else + expected = @conn.quoted_date(time) + end assert_equal expected, @conn.type_cast(time) end @@ -257,7 +265,7 @@ module ActiveRecord def test_type_cast_ar_object value = DatetimePrimaryKey.new(id: @time) - assert_equal "2017-02-14 12:34:56.789000", @connection.type_cast(value) + assert_equal @connection.type_cast(value.id), @connection.type_cast(value) end end end diff --git a/activerecord/test/cases/relation/mutation_test.rb b/activerecord/test/cases/relation/mutation_test.rb index dea787c07f..a37a2186ed 100644 --- a/activerecord/test/cases/relation/mutation_test.rb +++ b/activerecord/test/cases/relation/mutation_test.rb @@ -3,39 +3,6 @@ require "models/post" module ActiveRecord class RelationMutationTest < ActiveRecord::TestCase - FakeKlass = Struct.new(:table_name, :name) do - extend ActiveRecord::Delegation::DelegateCache - inherited self - - def connection - Post.connection - end - - def relation_delegate_class(klass) - self.class.relation_delegate_class(klass) - end - - def attribute_alias?(name) - false - end - - def sanitize_sql(sql) - sql - end - - def sanitize_sql_for_order(sql) - sql - end - - def arel_attribute(name, table) - table[name] - end - end - - def relation - @relation ||= Relation.new FakeKlass.new("posts"), Post.arel_table, Post.predicate_builder - end - (Relation::MULTI_VALUE_METHODS - [:references, :extending, :order, :unscope, :select]).each do |method| test "##{method}!" do assert relation.public_send("#{method}!", :foo).equal?(relation) @@ -90,7 +57,7 @@ module ActiveRecord assert_equal [], relation.extending_values end - (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with]).each do |method| + (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with, :skip_query_cache]).each do |method| test "##{method}!" do assert relation.public_send("#{method}!", :foo).equal?(relation) assert_equal :foo, relation.public_send("#{method}_value") @@ -162,5 +129,15 @@ module ActiveRecord relation.distinct! :foo assert_equal :foo, relation.distinct_value end + + test "skip_query_cache!" do + relation.skip_query_cache! + assert relation.skip_query_cache_value + end + + private + def relation + @relation ||= Relation.new(FakeKlass, Post.arel_table, Post.predicate_builder) + end end end diff --git a/activerecord/test/cases/relation/where_clause_test.rb b/activerecord/test/cases/relation/where_clause_test.rb index f8eb0dee91..57d7b315b0 100644 --- a/activerecord/test/cases/relation/where_clause_test.rb +++ b/activerecord/test/cases/relation/where_clause_test.rb @@ -97,7 +97,7 @@ class ActiveRecord::Relation assert_equal expected, original.invert end - test "accept removes binary predicates referencing a given column" do + test "except removes binary predicates referencing a given column" do where_clause = WhereClause.new([ table["id"].in([1, 2, 3]), table["name"].eq(bind_param), @@ -111,6 +111,22 @@ class ActiveRecord::Relation assert_equal expected, where_clause.except("id", "name") end + test "except jumps over unhandled binds (like with OR) correctly" do + wcs = (0..9).map do |i| + WhereClause.new([table["id#{i}"].eq(bind_param)], [bind_attribute("id#{i}", i)]) + end + + wc = wcs[0] + wcs[1] + wcs[2].or(wcs[3]) + wcs[4] + wcs[5] + wcs[6].or(wcs[7]) + wcs[8] + wcs[9] + + expected = wcs[0] + wcs[2].or(wcs[3]) + wcs[5] + wcs[6].or(wcs[7]) + wcs[9] + actual = wc.except("id1", "id2", "id4", "id7", "id8") + + # Easier to read than the inspect of where_clause + assert_equal expected.ast.to_sql, actual.ast.to_sql + assert_equal expected.binds.map(&:value), actual.binds.map(&:value) + assert_equal expected, actual + end + test "ast groups its predicates with AND" do predicates = [ table["id"].in([1, 2, 3]), diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index a403824f1a..82b071fb98 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -8,24 +8,6 @@ module ActiveRecord class RelationTest < ActiveRecord::TestCase fixtures :posts, :comments, :authors, :author_addresses, :ratings - FakeKlass = Struct.new(:table_name, :name) do - extend ActiveRecord::Delegation::DelegateCache - - inherited self - - def self.connection - Post.connection - end - - def self.table_name - "fake_table" - end - - def self.sanitize_sql_for_order(sql) - sql - end - end - def test_construction relation = Relation.new(FakeKlass, :b, nil) assert_equal FakeKlass, relation.klass @@ -70,8 +52,8 @@ module ActiveRecord def test_has_values relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) - relation.where! relation.table[:id].eq(10) - assert_equal({ id: 10 }, relation.where_values_hash) + relation.where!(id: 10) + assert_equal({ "id" => 10 }, relation.where_values_hash) end def test_values_wrong_table @@ -90,7 +72,7 @@ module ActiveRecord end def test_table_name_delegates_to_klass - relation = Relation.new(FakeKlass.new("posts"), :b, Post.predicate_builder) + relation = Relation.new(FakeKlass, :b, Post.predicate_builder) assert_equal "posts", relation.table_name end @@ -101,28 +83,19 @@ module ActiveRecord def test_create_with_value relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) - hash = { hello: "world" } - relation.create_with_value = hash - assert_equal hash, relation.scope_for_create - end - - def test_create_with_value_with_wheres - relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) - relation.where! relation.table[:id].eq(10) relation.create_with_value = { hello: "world" } - assert_equal({ hello: "world", id: 10 }, relation.scope_for_create) + assert_equal({ "hello" => "world" }, relation.scope_for_create) end - # FIXME: is this really wanted or expected behavior? - def test_scope_for_create_is_cached + def test_create_with_value_with_wheres relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) assert_equal({}, relation.scope_for_create) - relation.where! relation.table[:id].eq(10) - assert_equal({}, relation.scope_for_create) + relation.where!(id: 10) + assert_equal({ "id" => 10 }, relation.scope_for_create) relation.create_with_value = { hello: "world" } - assert_equal({}, relation.scope_for_create) + assert_equal({ "hello" => "world", "id" => 10 }, relation.scope_for_create) end def test_bad_constants_raise_errors diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 5767dec315..316ea75e36 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -15,7 +15,6 @@ require "models/car" require "models/engine" require "models/tyre" require "models/minivan" -require "models/aircraft" require "models/possession" require "models/reader" require "models/categorization" @@ -420,123 +419,6 @@ class RelationTest < ActiveRecord::TestCase assert_equal [2, 4, 6, 8, 10], even_ids.sort end - def test_none - assert_no_queries(ignore_none: false) do - assert_equal [], Developer.none - assert_equal [], Developer.all.none - end - end - - def test_none_chainable - assert_no_queries(ignore_none: false) do - assert_equal [], Developer.none.where(name: "David") - end - end - - def test_none_chainable_to_existing_scope_extension_method - assert_no_queries(ignore_none: false) do - assert_equal 1, Topic.anonymous_extension.none.one - end - end - - def test_none_chained_to_methods_firing_queries_straight_to_db - assert_no_queries(ignore_none: false) do - assert_equal [], Developer.none.pluck(:id, :name) - assert_equal 0, Developer.none.delete_all - assert_equal 0, Developer.none.update_all(name: "David") - assert_equal 0, Developer.none.delete(1) - assert_equal false, Developer.none.exists?(1) - end - end - - def test_null_relation_content_size_methods - assert_no_queries(ignore_none: false) do - assert_equal 0, Developer.none.size - assert_equal 0, Developer.none.count - assert_equal true, Developer.none.empty? - assert_equal true, Developer.none.none? - assert_equal false, Developer.none.any? - assert_equal false, Developer.none.one? - assert_equal false, Developer.none.many? - end - end - - def test_null_relation_calculations_methods - assert_no_queries(ignore_none: false) do - assert_equal 0, Developer.none.count - assert_equal 0, Developer.none.calculate(:count, nil) - assert_nil Developer.none.calculate(:average, "salary") - end - end - - def test_null_relation_metadata_methods - assert_equal "", Developer.none.to_sql - assert_equal({}, Developer.none.where_values_hash) - end - - def test_null_relation_where_values_hash - assert_equal({ "salary" => 100_000 }, Developer.none.where(salary: 100_000).where_values_hash) - end - - def test_null_relation_sum - ac = Aircraft.new - assert_equal Hash.new, ac.engines.group(:id).sum(:id) - assert_equal 0, ac.engines.count - ac.save - assert_equal Hash.new, ac.engines.group(:id).sum(:id) - 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 - ac.save - assert_equal Hash.new, ac.engines.group(:id).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 - ac.save - assert_equal Hash.new, ac.engines.group(:id).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_nil ac.engines.average(:id) - ac.save - assert_equal Hash.new, ac.engines.group(:car_id).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_nil ac.engines.minimum(:id) - ac.save - assert_equal Hash.new, ac.engines.group(:car_id).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_nil ac.engines.maximum(:id) - ac.save - assert_equal Hash.new, ac.engines.group(:car_id).maximum(:id) - assert_nil ac.engines.maximum(:id) - end - - def test_null_relation_in_where_condition - assert_operator Comment.count, :>, 0 # precondition, make sure there are comments. - assert_equal 0, Comment.where(post_id: Post.none).to_a.size - end - def test_joins_with_nil_argument assert_nothing_raised { DependentFirm.joins(nil).first } end @@ -586,14 +468,6 @@ class RelationTest < ActiveRecord::TestCase assert_nothing_raised { Topic.reorder([]) } end - def test_scoped_responds_to_delegated_methods - relation = Topic.all - - ["map", "uniq", "sort", "insert", "delete", "update"].each do |method| - assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}" - end - end - def test_respond_to_delegates_to_arel relation = Topic.all fake_arel = Struct.new(:responds) { @@ -1482,7 +1356,7 @@ class RelationTest < ActiveRecord::TestCase assert_equal bird, Bird.find_or_initialize_by(name: "bob") end - def test_explicit_create_scope + def test_explicit_create_with hens = Bird.where(name: "hen") assert_equal "hen", hens.new.name @@ -1911,15 +1785,15 @@ class RelationTest < ActiveRecord::TestCase end test "using a custom table affects the wheres" do - table_alias = Post.arel_table.alias("omg_posts") + post = posts(:welcome) + + assert_equal post, custom_post_relation.where!(title: post.title).take + end - table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias) - predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata) - relation = ActiveRecord::Relation.new(Post, table_alias, predicate_builder) - relation.where!(foo: "bar") + test "using a custom table with joins affects the joins" do + post = posts(:welcome) - node = relation.arel.constraints.first.grep(Arel::Attributes::Attribute).first - assert_equal table_alias, node.relation + assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).take end test "#load" do @@ -2034,4 +1908,55 @@ class RelationTest < ActiveRecord::TestCase assert_equal 2, posts.to_a.length end + + test "#skip_query_cache!" do + Post.cache do + assert_queries(1) do + Post.all.load + Post.all.load + end + + assert_queries(2) do + Post.all.skip_query_cache!.load + Post.all.skip_query_cache!.load + end + end + end + + test "#skip_query_cache! with an eager load" do + Post.cache do + assert_queries(1) do + Post.eager_load(:comments).load + Post.eager_load(:comments).load + end + + assert_queries(2) do + Post.eager_load(:comments).skip_query_cache!.load + Post.eager_load(:comments).skip_query_cache!.load + end + end + end + + test "#skip_query_cache! with a preload" do + Post.cache do + assert_queries(2) do + Post.preload(:comments).load + Post.preload(:comments).load + end + + assert_queries(4) do + Post.preload(:comments).skip_query_cache!.load + Post.preload(:comments).skip_query_cache!.load + end + end + end + + private + def custom_post_relation + table_alias = Post.arel_table.alias("omg_posts") + table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias) + predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata) + + ActiveRecord::Relation.create(Post, table_alias, predicate_builder) + end end diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb index 89fb434b27..a8c79628e7 100644 --- a/activerecord/test/cases/scoping/default_scoping_test.rb +++ b/activerecord/test/cases/scoping/default_scoping_test.rb @@ -332,7 +332,7 @@ class DefaultScopingTest < ActiveRecord::TestCase def test_create_with_merge aaron = PoorDeveloperCalledJamis.create_with(name: "foo", salary: 20).merge( - PoorDeveloperCalledJamis.create_with(name: "Aaron")).new + PoorDeveloperCalledJamis.create_with(name: "Aaron")).new assert_equal 20, aaron.salary assert_equal "Aaron", aaron.name @@ -342,6 +342,11 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal "Aaron", aaron.name end + def test_create_with_using_both_string_and_symbol + jamis = PoorDeveloperCalledJamis.create_with(name: "foo").create_with("name" => "Aaron").new + assert_equal "Aaron", jamis.name + end + def test_create_with_reset jamis = PoorDeveloperCalledJamis.create_with(name: "Aaron").create_with(nil).new assert_equal "Jamis", jamis.name @@ -372,11 +377,39 @@ class DefaultScopingTest < ActiveRecord::TestCase Comment.joins(:post).count end + def test_joins_not_affected_by_scope_other_than_default_or_unscoped + without_scope_on_post = Comment.joins(:post).to_a + with_scope_on_post = nil + Post.where(id: [1, 5, 6]).scoping do + with_scope_on_post = Comment.joins(:post).to_a + end + + assert_equal with_scope_on_post, without_scope_on_post + end + def test_unscoped_with_joins_should_not_have_default_scope assert_equal SpecialPostWithDefaultScope.unscoped { Comment.joins(:special_post_with_default_scope).to_a }, Comment.joins(:post).to_a end + def test_sti_association_with_unscoped_not_affected_by_default_scope + post = posts(:thinking) + comments = [comments(:does_it_hurt)] + + post.special_comments.update_all(deleted_at: Time.now) + + assert_raises(ActiveRecord::RecordNotFound) { Post.joins(:special_comments).find(post.id) } + assert_equal [], post.special_comments + + SpecialComment.unscoped do + assert_equal post, Post.joins(:special_comments).find(post.id) + assert_equal comments, Post.joins(:special_comments).find(post.id).special_comments + assert_equal comments, Post.eager_load(:special_comments).find(post.id).special_comments + assert_equal comments, Post.includes(:special_comments).find(post.id).special_comments + assert_equal comments, Post.preload(:special_comments).find(post.id).special_comments + end + end + def test_default_scope_select_ignored_by_aggregations assert_equal DeveloperWithSelect.all.to_a.count, DeveloperWithSelect.count end diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb index eecf923046..dc2d421cd7 100644 --- a/activerecord/test/models/comment.rb +++ b/activerecord/test/models/comment.rb @@ -54,6 +54,7 @@ class Comment < ActiveRecord::Base end class SpecialComment < Comment + default_scope { where(deleted_at: nil) } end class SubSpecialComment < SpecialComment diff --git a/activerecord/test/models/parrot.rb b/activerecord/test/models/parrot.rb index 1e5f9285a8..255ac19365 100644 --- a/activerecord/test/models/parrot.rb +++ b/activerecord/test/models/parrot.rb @@ -8,7 +8,7 @@ class Parrot < ActiveRecord::Base validates_presence_of :name - attr_accessor :cancel_save_from_callback + attribute :cancel_save_from_callback before_save :cancel_save_callback_method, if: :cancel_save_from_callback def cancel_save_callback_method throw(:abort) diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index ed64e0ee52..4aba336b01 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -199,6 +199,11 @@ class FirstPost < ActiveRecord::Base has_one :comment, foreign_key: :post_id end +class TaggedPost < Post + has_many :taggings, -> { rewhere(taggable_type: "TaggedPost") }, as: :taggable + has_many :tags, through: :taggings +end + class PostWithDefaultInclude < ActiveRecord::Base self.inheritance_column = :disabled self.table_name = "posts" @@ -276,3 +281,35 @@ end class SubConditionalStiPost < ConditionalStiPost end + +class FakeKlass + extend ActiveRecord::Delegation::DelegateCache + + inherited self + + class << self + def connection + Post.connection + end + + def table_name + "posts" + end + + def attribute_alias?(name) + false + end + + def sanitize_sql(sql) + sql + end + + def sanitize_sql_for_order(sql) + sql + end + + def arel_attribute(name, table) + table[name] + end + end +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index f534e9c00e..90185ff6c5 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -189,6 +189,7 @@ ActiveRecord::Schema.define do t.string :resource_id t.string :resource_type t.integer :developer_id + t.datetime :deleted_at end create_table :companies, force: true do |t| |