aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md6
-rw-r--r--activerecord/Rakefile39
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb3
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb14
-rw-r--r--activerecord/lib/active_record/database_configurations.rb2
-rw-r--r--activerecord/lib/active_record/migration/compatibility.rb26
-rw-r--r--activerecord/lib/active_record/querying.rb3
-rw-r--r--activerecord/lib/active_record/relation.rb4
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb6
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb22
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb2
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb9
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb50
-rw-r--r--activerecord/test/cases/base_test.rb5
-rw-r--r--activerecord/test/cases/calculations_test.rb5
-rw-r--r--activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb10
-rw-r--r--activerecord/test/cases/database_selector_test.rb4
-rw-r--r--activerecord/test/cases/relations_test.rb7
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb5
-rw-r--r--activerecord/test/models/company.rb2
-rw-r--r--activerecord/test/models/contract.rb8
-rw-r--r--activerecord/test/models/post.rb1
-rw-r--r--activerecord/test/models/reply.rb2
-rw-r--r--activerecord/test/models/topic.rb3
-rw-r--r--activerecord/test/schema/schema.rb1
25 files changed, 142 insertions, 97 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index f16a746b91..7b4f3c617c 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -4,12 +4,6 @@
*Ryuta Kamizono*
-* Chaining named scope is no longer leaking to class level querying methods.
-
- Fixes #14003.
-
- *Ryuta Kamizono*
-
* Allow applications to automatically switch connections.
Adds a middleware and configuration options that can be used in your
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 9824787658..90921dec8b 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -65,11 +65,42 @@ end
task adapter => "#{adapter}:env" do
adapter_short = adapter == "db2" ? adapter : adapter[/^[a-z0-9]+/]
puts [adapter, adapter_short].inspect
- (Dir["test/cases/**/*_test.rb"].reject {
+
+ failing_files = []
+
+ test_files = (Dir["test/cases/**/*_test.rb"].reject {
|x| x.include?("/adapters/")
- } + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).all? do |file|
- sh(Gem.ruby, "-w", "-Itest", file)
- end || raise("Failures")
+ } + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).sort
+
+ if ENV["BUILDKITE_PARALLEL_JOB_COUNT"]
+ n = ENV["BUILDKITE_PARALLEL_JOB"].to_i
+ m = ENV["BUILDKITE_PARALLEL_JOB_COUNT"].to_i
+
+ test_files = test_files.each_slice(m).map { |slice| slice[n] }.compact
+ end
+
+ test_files.each do |file|
+ puts "--- #{file}"
+ success = sh(Gem.ruby, "-w", "-Itest", file)
+ unless success
+ failing_files << file
+ puts "^^^ +++"
+ end
+ puts
+ end
+
+ puts "--- All tests completed"
+ unless failing_files.empty?
+ puts "^^^ +++"
+ puts
+ puts "Failed in:"
+ failing_files.each do |file|
+ puts " #{file}"
+ end
+ puts
+
+ exit 1
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index b0c0beac0e..c3d4eab562 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -209,8 +209,7 @@ module ActiveRecord
# This method is abstract in the sense that it relies on
# +count_records+, which is a method descendants have to provide.
def size
- if !find_target?
- loaded! unless loaded?
+ if !find_target? || loaded?
target.size
elsif @association_ids
@association_ids.size
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index 6f67934a79..5972846940 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -52,7 +52,11 @@ module ActiveRecord
# If the collection is empty the target is set to an empty array and
# the loaded flag is set to true as well.
def count_records
- count = counter_cache_value || scope.count(:all)
+ count = if reflection.has_cached_counter?
+ owner._read_attribute(reflection.counter_cache_column).to_i
+ else
+ scope.count(:all)
+ end
# If there's nothing in the database and @target has no new records
# we are certain the current target is an empty array. This is a
@@ -62,14 +66,6 @@ module ActiveRecord
[association_scope.limit_value, count].compact.min
end
- def counter_cache_value
- reflection.has_cached_counter? ? owner._read_attribute(reflection.counter_cache_column).to_i : nil
- end
-
- def find_target?
- super && !counter_cache_value&.zero?
- end
-
def update_counter(difference, reflection = reflection())
if reflection.has_cached_counter?
owner.increment!(reflection.counter_cache_column, difference)
diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb
index c36b87829e..9879b01d3a 100644
--- a/activerecord/lib/active_record/database_configurations.rb
+++ b/activerecord/lib/active_record/database_configurations.rb
@@ -158,7 +158,7 @@ module ActiveRecord
configs
else
configs.map do |config|
- ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, config.spec_name, url, config.config)
+ ActiveRecord::DatabaseConfigurations::UrlConfig.new(config.env_name, config.spec_name, url, config.config)
end
end
else
diff --git a/activerecord/lib/active_record/migration/compatibility.rb b/activerecord/lib/active_record/migration/compatibility.rb
index 94906a2943..abc939826b 100644
--- a/activerecord/lib/active_record/migration/compatibility.rb
+++ b/activerecord/lib/active_record/migration/compatibility.rb
@@ -77,18 +77,18 @@ module ActiveRecord
class V5_1 < V5_2
def change_column(table_name, column_name, type, options = {})
- if adapter_name == "PostgreSQL"
+ if connection.adapter_name == "PostgreSQL"
super(table_name, column_name, type, options.except(:default, :null, :comment))
- change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
- change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
- change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
+ connection.change_column_default(table_name, column_name, options[:default]) if options.key?(:default)
+ connection.change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
+ connection.change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
else
super
end
end
def create_table(table_name, options = {})
- if adapter_name == "Mysql2"
+ if connection.adapter_name == "Mysql2"
super(table_name, options: "ENGINE=InnoDB", **options)
else
super
@@ -110,13 +110,13 @@ module ActiveRecord
end
def create_table(table_name, options = {})
- if adapter_name == "PostgreSQL"
+ if connection.adapter_name == "PostgreSQL"
if options[:id] == :uuid && !options.key?(:default)
options[:default] = "uuid_generate_v4()"
end
end
- unless adapter_name == "Mysql2" && options[:id] == :bigint
+ unless connection.adapter_name == "Mysql2" && options[:id] == :bigint
if [:integer, :bigint].include?(options[:id]) && !options.key?(:default)
options[:default] = nil
end
@@ -190,7 +190,7 @@ module ActiveRecord
if options[:name].present?
options[:name].to_s
else
- index_name(table_name, column: column_names)
+ connection.index_name(table_name, column: column_names)
end
super
end
@@ -210,15 +210,17 @@ module ActiveRecord
end
def index_name_for_remove(table_name, options = {})
- index_name = index_name(table_name, options)
+ index_name = connection.index_name(table_name, options)
- unless index_name_exists?(table_name, index_name)
+ unless connection.index_name_exists?(table_name, index_name)
if options.is_a?(Hash) && options.has_key?(:name)
options_without_column = options.dup
options_without_column.delete :column
- index_name_without_column = index_name(table_name, options_without_column)
+ index_name_without_column = connection.index_name(table_name, options_without_column)
- return index_name_without_column if index_name_exists?(table_name, index_name_without_column)
+ if connection.index_name_exists?(table_name, index_name_without_column)
+ return index_name_without_column
+ end
end
raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb
index 8c1b2e2be1..2a27f53f06 100644
--- a/activerecord/lib/active_record/querying.rb
+++ b/activerecord/lib/active_record/querying.rb
@@ -40,8 +40,7 @@ module ActiveRecord
def find_by_sql(sql, binds = [], preparable: nil, &block)
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
column_types = result_set.column_types.dup
- cached_columns_hash = connection.schema_cache.columns_hash(table_name)
- cached_columns_hash.each_key { |k| column_types.delete k }
+ attribute_types.each_key { |k| column_types.delete k }
message_bus = ActiveSupport::Notifications.instrumenter
payload = {
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 347d745d19..f98d9bb2c0 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -321,12 +321,12 @@ module ActiveRecord
# Please check unscoped if you want to remove all previous scopes (including
# the default_scope) during the execution of a block.
def scoping
- @delegate_to_klass && klass.current_scope(true) ? yield : _scoping(self) { yield }
+ @delegate_to_klass ? yield : _scoping(self) { yield }
end
def _exec_scope(*args, &block) # :nodoc:
@delegate_to_klass = true
- _scoping(nil) { instance_exec(*args, &block) || self }
+ instance_exec(*args, &block) || self
ensure
@delegate_to_klass = false
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index cef31bea94..bdd3c540bb 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -186,11 +186,9 @@ module ActiveRecord
relation = apply_join_dependency
relation.pluck(*column_names)
else
- disallow_raw_sql!(column_names)
+ klass.disallow_raw_sql!(column_names)
relation = spawn
- relation.select_values = column_names.map { |cn|
- @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn
- }
+ relation.select_values = column_names
result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
result.cast_values(klass.attribute_types)
end
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index eb80aab701..75976aa8fc 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -1052,11 +1052,13 @@ module ActiveRecord
def arel_columns(columns)
columns.flat_map do |field|
- if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
- arel_attribute(field)
- elsif Symbol === field
- connection.quote_table_name(field.to_s)
- elsif Proc === field
+ case field
+ when Symbol
+ field = field.to_s
+ arel_column(field) { connection.quote_table_name(field) }
+ when String
+ arel_column(field) { field }
+ when Proc
field.call
else
field
@@ -1064,6 +1066,16 @@ module ActiveRecord
end
end
+ def arel_column(field)
+ field = klass.attribute_alias(field) if klass.attribute_alias?(field)
+
+ if klass.columns_hash.key?(field) && !from_clause.value
+ arel_attribute(field)
+ else
+ yield
+ end
+ end
+
def reverse_sql_order(order_query)
if order_query.empty?
return [arel_attribute(primary_key).desc] if primary_key
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 8cf4fc469f..7874c4c35a 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -8,7 +8,7 @@ module ActiveRecord
module SpawnMethods
# This is overridden by Associations::CollectionProxy
def spawn #:nodoc:
- @delegate_to_klass && klass.current_scope(true) ? klass.all : clone
+ @delegate_to_klass ? klass.all : clone
end
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index c01138c059..3525fa2ab8 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -448,8 +448,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
end
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, Post.find(2).author_with_select.attributes.size
+ assert_equal 1, Post.includes(:author_with_select).find(2).author_with_select.attributes.size
+ end
+
+ def test_custom_attribute_with_select
+ assert_equal 2, Company.find(2).firm_with_select.attributes.size
+ assert_equal 2, Company.includes(:firm_with_select).find(2).firm_with_select.attributes.size
end
def test_belongs_to_without_counter_cache_option
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index bf44be1811..7d669198ca 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1230,10 +1230,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_predicate Ship.reflect_on_association(:treasures), :has_cached_counter?
# Count should come from sql count() of treasures rather than treasures_count attribute
- assert_queries(1) do
- assert_equal ship.treasures.size, 0
- assert_predicate ship.treasures, :loaded?
- end
+ assert_equal ship.treasures.size, 0
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
ship.treasures.create(name: "Gold")
@@ -1354,20 +1351,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
post = posts(:welcome)
assert_no_queries do
assert_not_empty post.comments
- assert_equal 2, post.comments.size
- assert_not_predicate post.comments, :loaded?
- end
- post = posts(:misc_by_bob)
- assert_no_queries do
- assert_empty post.comments
- assert_predicate post.comments, :loaded?
- end
- end
-
- def test_empty_association_loading_with_counter_cache
- post = posts(:misc_by_bob)
- assert_no_queries do
- assert_empty post.comments.to_a
end
end
@@ -1755,6 +1738,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_nil posts.first
end
+ def test_destroy_all_on_desynced_counter_cache_association
+ category = categories(:general)
+ assert_operator category.categorizations.count, :>, 0
+
+ category.categorizations.destroy_all
+ assert_equal 0, category.categorizations.count
+ end
+
def test_destroy_on_association_clears_scope
author = Author.create!(name: "Gannon")
posts = author.posts
@@ -2004,6 +1995,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_predicate company.clients, :loaded?
end
+ def test_counter_cache_on_unloaded_association
+ car = Car.create(name: "My AppliCar")
+ assert_equal 0, car.engines.size
+ end
+
def test_ids_reader_cache_not_used_for_size_when_association_is_dirty
firm = Firm.create!(name: "Startup")
assert_equal 0, firm.client_ids.size
@@ -2019,24 +2015,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [3, 11], firm.client_ids
end
- def test_zero_counter_cache_usage_on_unloaded_association
- car = Car.create!(name: "My AppliCar")
- assert_no_queries do
- assert_equal car.engines.size, 0
- assert_predicate car.engines, :loaded?
- end
- end
-
- def test_counter_cache_on_new_record_unloaded_association
- car = Car.new(name: "My AppliCar")
- # Ensure no schema queries inside assertion
- Engine.primary_key
- assert_no_queries do
- assert_equal car.engines.size, 0
- assert_predicate car.engines, :loaded?
- end
- end
-
def test_get_ids_ignores_include_option
assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 363593ca19..1b8f748bad 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1226,14 +1226,15 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_attribute_names
- assert_equal ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description"],
- Company.attribute_names
+ expected = ["id", "type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id", "description", "metadata"]
+ assert_equal expected, Company.attribute_names
end
def test_has_attribute
assert Company.has_attribute?("id")
assert Company.has_attribute?("type")
assert Company.has_attribute?("name")
+ assert Company.has_attribute?("metadata")
assert_not Company.has_attribute?("lastname")
assert_not Company.has_attribute?("age")
end
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 850bc49676..b001667ac9 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -690,8 +690,9 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_pluck_not_auto_table_name_prefix_if_column_joined
- Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
- assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
+ company = Company.create!(name: "test", contracts: [Contract.new(developer_id: 7)])
+ metadata = company.contracts.first.metadata
+ assert_equal [metadata], Company.joins(:contracts).pluck(:metadata)
end
def test_pluck_with_selection_clause
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 225cccc62c..515bf5df06 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
@@ -72,6 +72,16 @@ module ActiveRecord
assert_equal expected, actual
end
+ def test_resolver_with_database_uri_and_multiple_envs
+ ENV["DATABASE_URL"] = "postgres://localhost"
+ ENV["RAILS_ENV"] = "test"
+
+ config = { "production" => { "adapter" => "postgresql", "database" => "foo_prod" }, "test" => { "adapter" => "postgresql", "database" => "foo_test" } }
+ actual = resolve_spec(:test, config)
+ expected = { "adapter" => "postgresql", "database" => "foo_test", "host" => "localhost", "name" => "test" }
+ 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" } }
diff --git a/activerecord/test/cases/database_selector_test.rb b/activerecord/test/cases/database_selector_test.rb
index 4106a6ec46..fd02d2acb4 100644
--- a/activerecord/test/cases/database_selector_test.rb
+++ b/activerecord/test/cases/database_selector_test.rb
@@ -11,6 +11,10 @@ module ActiveRecord
@session = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session.new(@session_store)
end
+ teardown do
+ ActiveRecord::Base.connection_handlers = { writing: ActiveRecord::Base.default_connection_handler }
+ end
+
def test_empty_session
assert_equal Time.at(0), @session.last_write_timestamp
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 0ab0459c38..857d743605 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -14,6 +14,7 @@ require "models/person"
require "models/computer"
require "models/reply"
require "models/company"
+require "models/contract"
require "models/bird"
require "models/car"
require "models/engine"
@@ -1815,6 +1816,12 @@ class RelationTest < ActiveRecord::TestCase
assert_equal [1, 1, 1], posts.map(&:author_address_id)
end
+ test "joins with select custom attribute" do
+ contract = Company.create!(name: "test").contracts.create!
+ company = Company.joins(:contracts).select(:id, :metadata).find(contract.company_id)
+ assert_equal contract.metadata, company.metadata
+ end
+
test "delegations do not leak to other classes" do
Topic.all.by_lifo
assert Topic.all.class.method_defined?(:by_lifo)
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 27f9df295f..1a3a95f168 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -447,9 +447,8 @@ class NamedScopingTest < ActiveRecord::TestCase
assert_equal [posts(:sti_comments)], Post.with_special_comments.with_post(4).to_a.uniq
end
- def test_chaining_doesnt_leak_conditions_to_another_scopes
- expected = Topic.where(approved: false).where(id: Topic.children.select(:parent_id))
- assert_equal expected.to_a, Topic.rejected.has_children.to_a
+ def test_class_method_in_scope
+ assert_equal [topics(:second)], topics(:first).approved_replies.ordered
end
def test_nested_scoping
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index 838f515aad..a0f48d23f1 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -13,6 +13,8 @@ class Company < AbstractCompany
has_many :contracts
has_many :developers, through: :contracts
+ attribute :metadata, :json
+
scope :of_first_firm, lambda {
joins(account: :firm).
where("firms.id" => 1)
diff --git a/activerecord/test/models/contract.rb b/activerecord/test/models/contract.rb
index 3f663375c4..89719775c4 100644
--- a/activerecord/test/models/contract.rb
+++ b/activerecord/test/models/contract.rb
@@ -5,7 +5,9 @@ class Contract < ActiveRecord::Base
belongs_to :developer, primary_key: :id
belongs_to :firm, foreign_key: "company_id"
- before_save :hi
+ attribute :metadata, :json
+
+ before_save :hi, :update_metadata
after_save :bye
attr_accessor :hi_count, :bye_count
@@ -19,6 +21,10 @@ class Contract < ActiveRecord::Base
@bye_count ||= 0
@bye_count += 1
end
+
+ def update_metadata
+ self.metadata = { company_id: company_id, developer_id: developer_id }
+ end
end
class NewContract < Contract
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index e32cc59399..65d1fce66d 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -31,6 +31,7 @@ class Post < ActiveRecord::Base
belongs_to :author_with_posts, -> { includes(:posts) }, class_name: "Author", foreign_key: :author_id
belongs_to :author_with_address, -> { includes(:author_address) }, class_name: "Author", foreign_key: :author_id
+ belongs_to :author_with_select, -> { select(:id) }, class_name: "Author", foreign_key: :author_id
def first_comment
super.body
diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb
index 0807bcf875..b35623a344 100644
--- a/activerecord/test/models/reply.rb
+++ b/activerecord/test/models/reply.rb
@@ -7,6 +7,8 @@ class Reply < Topic
belongs_to :topic_with_primary_key, class_name: "Topic", primary_key: "title", foreign_key: "parent_title", counter_cache: "replies_count", touch: true
has_many :replies, class_name: "SillyReply", dependent: :destroy, foreign_key: "parent_id"
has_many :silly_unique_replies, dependent: :destroy, foreign_key: "parent_id"
+
+ scope :ordered, -> { Reply.order(:id) }
end
class SillyReply < Topic
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index fdb461ed7f..75890c327a 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -10,9 +10,6 @@ class Topic < ActiveRecord::Base
scope :approved, -> { where(approved: true) }
scope :rejected, -> { where(approved: false) }
- scope :children, -> { where.not(parent_id: nil) }
- scope :has_children, -> { where(id: Topic.children.select(:parent_id)) }
-
scope :scope_with_lambda, lambda { all }
scope :by_lifo, -> { where(author_name: "lifo") }
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 86d5a67a13..349b8afc48 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -247,6 +247,7 @@ ActiveRecord::Schema.define do
create_table :contracts, force: true do |t|
t.references :developer, index: false
t.references :company, index: false
+ t.string :metadata
end
create_table :customers, force: true do |t|