aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2014-10-31 09:10:40 -0400
committereileencodes <eileencodes@gmail.com>2015-01-02 17:15:30 -0500
commit69d05ae3e52fa382748982ad06c0d0a1014ebc91 (patch)
tree840d0d8658e1332ceb8b2454f780530872bd8397 /activerecord/lib
parent08acb4bccba5b64a233eb7c2ea1b0cd09881d2cb (diff)
downloadrails-69d05ae3e52fa382748982ad06c0d0a1014ebc91.tar.gz
rails-69d05ae3e52fa382748982ad06c0d0a1014ebc91.tar.bz2
rails-69d05ae3e52fa382748982ad06c0d0a1014ebc91.zip
Add RuntimeReflection for recursive access to chain
The `RuntimeReflection` class allows the reflection to be accessed at runtime - then we always know which reflection we are accessing in the chain. The `#get_chain` method then allows us to recursively access the chain through the `RuntimeReflection`.
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb57
1 files changed, 54 insertions, 3 deletions
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index 668798c246..95c4cf2500 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -34,9 +34,10 @@ module ActiveRecord
scope = klass.unscoped
owner = association.owner
alias_tracker = AliasTracker.empty connection
+ chain = get_chain(reflection, association)
scope.extending! Array(reflection.options[:extend])
- add_constraints(scope, owner, klass, reflection, alias_tracker)
+ add_constraints(scope, owner, klass, reflection, alias_tracker, chain)
end
def join_type
@@ -129,9 +130,59 @@ module ActiveRecord
scope = scope.joins(join(foreign_table, constraint))
end
- def add_constraints(scope, owner, assoc_klass, refl, tracker)
- chain = refl.chain
+ class RuntimeReflection
+ def initialize(reflection, association)
+ @reflection = reflection
+ @association = association
+ end
+
+ def klass
+ @association.klass
+ end
+
+ def scope
+ @reflection.scope
+ end
+
+ def table_name
+ if @reflection.polymorphic?
+ # If this is a polymorphic belongs_to, we want to get the klass from the
+ # association because it depends on the polymorphic_type attribute of
+ # the owner
+ klass.table_name
+ else
+ @reflection.table_name
+ end
+ end
+
+ def plural_name
+ @reflection.plural_name
+ end
+
+ def join_keys(assoc_klass)
+ @reflection.join_keys(assoc_klass)
+ end
+
+ def type
+ @reflection.type
+ end
+
+ def constraints
+ @reflection.constraints
+ end
+
+ def source_type_info
+ @reflection.source_type_info
+ end
+ end
+
+ def get_chain(reflection, association)
+ chain = reflection.chain.dup
+ chain[0] = RuntimeReflection.new(reflection, association)
+ chain
+ end
+ def add_constraints(scope, owner, assoc_klass, refl, tracker, chain)
tables = construct_tables(chain, assoc_klass, refl, tracker)
owner_reflection = chain.last