Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
byroot committed May 10, 2024
1 parent 7036467 commit a35633b
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ def initialize(scope, association_key_name)
def eql?(other)
association_key_name == other.association_key_name &&
scope.table_name == other.scope.table_name &&
scope.connection_specification_name == other.scope.connection_specification_name &&
scope.model.connection_specification_name == other.scope.model.connection_specification_name &&
scope.values_for_queries == other.scope.values_for_queries
end

def hash
[association_key_name, scope.table_name, scope.connection_specification_name, scope.values_for_queries].hash
[association_key_name, scope.model.table_name, scope.model.connection_specification_name, scope.values_for_queries].hash
end

def records_for(loaders)
Expand Down
11 changes: 10 additions & 1 deletion activerecord/lib/active_record/relation/delegation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,16 @@ def #{method}(...)

delegate :primary_key, :lease_connection, :connection, :with_connection,
:table_name, :transaction, :arel_table, :uncached, :sanitize_sql_like,
to: :klass
:unscoped, to: :klass

# TODO: scoped delegate
[:find_signed, :find_signed!, :delete, :find_by_token_for, :find_by_token_for!, :upsert_all, :insert_all, :insert_all!].each do |method|
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{method}(...)
scoping { klass.#{method}(...) }
end
RUBY
end

module ClassSpecificRelation # :nodoc:
extend ActiveSupport::Concern
Expand Down
6 changes: 3 additions & 3 deletions activerecord/lib/active_record/relation/finder_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ def sole

if found.nil?
raise_record_not_found_exception!
elsif undesired.present?
raise ActiveRecord::SoleRecordExceeded.new(self)
else
elsif undesired.nil?
found
else
raise ActiveRecord::SoleRecordExceeded.new(model)
end
end

Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/relation/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ def in_order_of(column, values)
references = column_references([column])
self.references_values |= references unless references.empty?

values = values.map { |value| type_caster.type_cast_for_database(column, value) }
values = values.map { |value| model.type_caster.type_cast_for_database(column, value) }
arel_column = column.is_a?(Arel::Nodes::SqlLiteral) ? column : order_column(column.to_s)

where_clause =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -824,18 +824,18 @@ def test_association_proxy_transaction_method_starts_transaction_in_association_
end

def test_caching_of_columns
david = Developer.find(1)
Developer.find(1)
# clear cache possibly created by other tests
Project.reset_column_information

assert_queries_count(include_schema: true) { david.projects.columns }
assert_no_queries { david.projects.columns }
assert_queries_count(include_schema: true) { Project.columns }
assert_no_queries { Project.columns }

## and again to verify that reset_column_information clears the cache correctly
Project.reset_column_information

assert_queries_count(include_schema: true) { david.projects.columns }
assert_no_queries { david.projects.columns }
assert_queries_count(include_schema: true) { Project.columns }
assert_no_queries { Project.columns }
end

def test_attributes_are_being_set_when_initialized_from_habtm_association_with_where_clause
Expand Down
22 changes: 16 additions & 6 deletions activerecord/test/cases/relation/delegation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class QueryingMethodsDelegationTest < ActiveRecord::TestCase
ActiveRecord::SpawnMethods.public_instance_methods(false) - [:spawn, :merge!] +
ActiveRecord::QueryMethods.public_instance_methods(false).reject { |method|
method.end_with?("=", "!", "?", "value", "values", "clause")
} - [:reverse_order, :arel, :extensions, :construct_join_dependency] + [
} - [:all, :reverse_order, :arel, :extensions, :construct_join_dependency] + [
:any?, :many?, :none?, :one?,
:first_or_create, :first_or_create!, :first_or_initialize,
:find_or_create_by, :find_or_create_by!, :find_or_initialize_by,
Expand All @@ -89,14 +89,24 @@ class DelegationCachingTest < ActiveRecord::TestCase

test "delegation doesn't override methods defined in other relation subclasses" do
# precondition, some methods are available on ActiveRecord::Relation subclasses
# but not ActiveRecord::Relation itself. Here `delete` is just an example.
assert_equal false, ActiveRecord::Relation.method_defined?(:delete)
assert_equal true, ActiveRecord::Associations::CollectionProxy.method_defined?(:delete)
# but not ActiveRecord::Relation itself. Here `clear` is just an example.
assert_equal false, ActiveRecord::Relation.method_defined?(:clear)
assert_equal true, ActiveRecord::Associations::CollectionProxy.method_defined?(:clear)

project = projects(:active_record)
original_owner = project.developers_with_callbacks.method(:delete).owner
original_owner = project.developers_with_callbacks.method(:clear).owner
Developer.all.delete(12345)
assert_equal original_owner, project.developers_with_callbacks.method(:delete).owner
assert_equal original_owner, project.developers_with_callbacks.method(:clear).owner
end

test "delegation automatically delegate ActiveRecord::Base methods" do
assert_equal false, ActiveRecord::Relation.method_defined?(:superclass)
assert_equal true, ActiveRecord::Base.respond_to?(:superclass)

error = assert_raises NoMethodError do
Developer.all.superclass
end
assert_equal :superclass, error.name
end
end
end

0 comments on commit a35633b

Please sign in to comment.