diff options
author | eileencodes <eileencodes@gmail.com> | 2014-10-31 09:10:40 -0400 |
---|---|---|
committer | eileencodes <eileencodes@gmail.com> | 2015-01-02 17:15:30 -0500 |
commit | 69d05ae3e52fa382748982ad06c0d0a1014ebc91 (patch) | |
tree | 840d0d8658e1332ceb8b2454f780530872bd8397 | |
parent | 08acb4bccba5b64a233eb7c2ea1b0cd09881d2cb (diff) | |
download | rails-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`.
-rw-r--r-- | activerecord/lib/active_record/associations/association_scope.rb | 57 |
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 |