From 08acb4bccba5b64a233eb7c2ea1b0cd09881d2cb Mon Sep 17 00:00:00 2001 From: eileencodes Date: Sat, 18 Oct 2014 14:53:21 -0400 Subject: Add PolymorphicReflection and constraints method `#constraints` builds a flattened version of `scope_chain` to allow it to be accessible without requiring an index when iterating over the `scope_chain` --- activerecord/lib/active_record/reflection.rb | 59 +++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index dd746a4e10..1bc92b1587 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -161,7 +161,12 @@ module ActiveRecord macro end + + def constraints + scope ? [scope] : [] + end end + # Base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. # @@ -697,13 +702,59 @@ module ActiveRecord def chain @chain ||= begin a = source_reflection.chain - b = through_reflection.chain + b = through_reflection.chain.map(&:dup) + + if options[:source_type] + b[0] = PolymorphicReflection.new(b[0], self) + end + chain = a + b chain[0] = self # Use self so we don't lose the information from :source_type chain end end + class PolymorphicReflection + def initialize(reflection, prev_reflection) + @reflection = reflection + @prev_reflection = prev_reflection + end + + def klass + @reflection.klass + end + + def scope + @reflection.scope + end + + def table_name + @reflection.table_name + 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 + [source_type_info] + end + + def source_type_info + type = @prev_reflection.foreign_type + source_type = @prev_reflection.options[:source_type] + lambda { |object| where(type => source_type) } + end + end + # Consider the following example: # # class Person @@ -855,6 +906,12 @@ module ActiveRecord check_validity_of_inverse! end + def constraints + scope_chain = source_reflection.constraints + scope_chain << scope if scope + scope_chain + end + protected def actual_source_reflection # FIXME: this is a horrible name -- cgit v1.2.3 From 076682692cd363765e6e5235c691474a071a01de Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 4 Nov 2014 13:58:15 -0500 Subject: Refactor construct_tables method Move method structure into reflection classes for accessibly on each reflection rather than by traversing the chain. --- activerecord/lib/active_record/reflection.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 1bc92b1587..83771bd5dc 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -165,6 +165,11 @@ module ActiveRecord def constraints scope ? [scope] : [] end + + def alias_name(name, alias_tracker) + alias_name = "#{plural_name}_#{name}" + alias_tracker.aliased_table_for(table_name, alias_name) + end end # Base class for AggregateReflection and AssociationReflection. Objects of @@ -753,6 +758,11 @@ module ActiveRecord source_type = @prev_reflection.options[:source_type] lambda { |object| where(type => source_type) } end + + def alias_name(name, alias_tracker) + alias_name = "#{plural_name}_#{name}" + alias_tracker.aliased_table_for(table_name, alias_name) + end end # Consider the following example: -- cgit v1.2.3 From 5b0b3cce5c0ecef02f1f6f09aea1de44b9ca88cf Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 11 Nov 2014 14:10:42 -0500 Subject: Move `#alias_name` to `ReflectionProxy` class Putting the `#alias_name` into ReflectionProxy means we don't have to cache the `#alias_name` globally anymore - it's not cached per query. --- activerecord/lib/active_record/reflection.rb | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 83771bd5dc..1bc92b1587 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -165,11 +165,6 @@ module ActiveRecord def constraints scope ? [scope] : [] end - - def alias_name(name, alias_tracker) - alias_name = "#{plural_name}_#{name}" - alias_tracker.aliased_table_for(table_name, alias_name) - end end # Base class for AggregateReflection and AssociationReflection. Objects of @@ -758,11 +753,6 @@ module ActiveRecord source_type = @prev_reflection.options[:source_type] lambda { |object| where(type => source_type) } end - - def alias_name(name, alias_tracker) - alias_name = "#{plural_name}_#{name}" - alias_tracker.aliased_table_for(table_name, alias_name) - end end # Consider the following example: -- cgit v1.2.3 From e9684d6c8849767ad38cb3cc76cb628252a67ed6 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 1 Dec 2014 18:44:51 -0500 Subject: Clean up / refactor new reflection classes Move `RuntimeReflection` and `PolymorphicReflect` into Reflection. This allows the methods to inherit from `ThroughReflection` and DRY up the methods by removing duplicates. --- activerecord/lib/active_record/reflection.rb | 117 +++++++++++++++++---------- 1 file changed, 75 insertions(+), 42 deletions(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 1bc92b1587..ea469f881c 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -163,7 +163,7 @@ module ActiveRecord end def constraints - scope ? [scope] : [] + scope_chain.flatten end end @@ -714,47 +714,6 @@ module ActiveRecord end end - class PolymorphicReflection - def initialize(reflection, prev_reflection) - @reflection = reflection - @prev_reflection = prev_reflection - end - - def klass - @reflection.klass - end - - def scope - @reflection.scope - end - - def table_name - @reflection.table_name - 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 - [source_type_info] - end - - def source_type_info - type = @prev_reflection.foreign_type - source_type = @prev_reflection.options[:source_type] - lambda { |object| where(type => source_type) } - end - end - # Consider the following example: # # class Person @@ -934,5 +893,79 @@ module ActiveRecord delegate(*delegate_methods, to: :delegate_reflection) end + + class PolymorphicReflection < ThroughReflection + def initialize(reflection, prev_reflection) + @reflection = reflection + @prev_reflection = prev_reflection + end + + def klass + @reflection.klass + end + + def scope + @reflection.scope + end + + def table_name + @reflection.table_name + 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 + [source_type_info] + end + + def source_type_info + type = @prev_reflection.foreign_type + source_type = @prev_reflection.options[:source_type] + lambda { |object| where(type => source_type) } + end + end + + class RuntimeReflection < PolymorphicReflection + attr_accessor :next + + def initialize(reflection, association) + @reflection = reflection + @association = association + end + + def klass + @association.klass + end + + def table_name + klass.table_name + end + + def constraints + @reflection.constraints + end + + def source_type_info + @reflection.source_type_info + end + + def alias_name(name, alias_tracker) + @alias ||= begin + alias_name = "#{plural_name}_#{name}_join" + table_name = klass.table_name + alias_tracker.aliased_table_for(table_name, alias_name) + end + end + end end end -- cgit v1.2.3 From f6729309a06f40b32e52f8ee8143d1b1da412597 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 2 Dec 2014 19:03:25 -0500 Subject: Assign the `#alias_name` to each reflection This makes the `#alias_name` more functional. --- activerecord/lib/active_record/reflection.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index ea469f881c..79c6504a18 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -936,7 +936,7 @@ module ActiveRecord end class RuntimeReflection < PolymorphicReflection - attr_accessor :next + attr_accessor :next, :alias_name def initialize(reflection, association) @reflection = reflection @@ -959,12 +959,8 @@ module ActiveRecord @reflection.source_type_info end - def alias_name(name, alias_tracker) - @alias ||= begin - alias_name = "#{plural_name}_#{name}_join" - table_name = klass.table_name - alias_tracker.aliased_table_for(table_name, alias_name) - end + def alias_candidate(name) + "#{plural_name}_#{name}_join" end end end -- cgit v1.2.3 From 16fafd658805407e2bda4f4bb06a70157c21f78a Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 9 Dec 2014 14:29:50 -0500 Subject: Move `alias_candiate` into `AbstractReflection` This moves `alias_candidate` out of the `ReflectionProxy` and into the `AbstractReflection` so it is shared by all reflections. Change `alias_name` to a method and and remove assignment in `#get_chain`. --- activerecord/lib/active_record/reflection.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 79c6504a18..111911b575 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -165,6 +165,10 @@ module ActiveRecord def constraints scope_chain.flatten end + + def alias_candidate(name) + "#{plural_name}_#{name}" + end end # Base class for AggregateReflection and AssociationReflection. Objects of @@ -936,7 +940,7 @@ module ActiveRecord end class RuntimeReflection < PolymorphicReflection - attr_accessor :next, :alias_name + attr_accessor :next def initialize(reflection, association) @reflection = reflection @@ -962,6 +966,10 @@ module ActiveRecord def alias_candidate(name) "#{plural_name}_#{name}_join" end + + def alias_name + Arel::Table.new(table_name) + end end end end -- cgit v1.2.3 From 96e277c03b7e62e33858ea9e254c9ed88625778f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Sun, 21 Dec 2014 17:51:16 -0500 Subject: Add `#all_includes` method to reflections `yield` instead of relying on checking if the reflection is equal to the `chain_head`. --- activerecord/lib/active_record/reflection.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 111911b575..25fda8f110 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -970,6 +970,8 @@ module ActiveRecord def alias_name Arel::Table.new(table_name) end + + def all_includes; yield; end end end end -- cgit v1.2.3 From b0d87a725af7d2c1e254780fa1052b210bcdec8c Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 31 Dec 2014 14:56:40 -0500 Subject: Cleanup methods, missing spacing and missing nodocs Add missing nodoc's Change `assoc_klass` argument name to `association_klass` Change `prev_reflection` argument name to `previous_reflection` Change `prev` to `previous_reflection` in `#get_chain` Switch use of `refl` and `reflection` in `#get_chain` so main parameter is not abbreviated. Add missing space in `#add_constraints` --- activerecord/lib/active_record/reflection.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'activerecord/lib/active_record/reflection.rb') diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 25fda8f110..7696ef13c7 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -149,7 +149,7 @@ module ActiveRecord JoinKeys = Struct.new(:key, :foreign_key) # :nodoc: - def join_keys(assoc_klass) + def join_keys(association_klass) JoinKeys.new(foreign_key, active_record_primary_key) end @@ -610,8 +610,8 @@ module ActiveRecord def belongs_to?; true; end - def join_keys(assoc_klass) - key = polymorphic? ? association_primary_key(assoc_klass) : association_primary_key + def join_keys(association_klass) + key = polymorphic? ? association_primary_key(association_klass) : association_primary_key JoinKeys.new(key, foreign_key) end @@ -706,7 +706,7 @@ module ActiveRecord def chain @chain ||= begin a = source_reflection.chain - b = through_reflection.chain.map(&:dup) + b = through_reflection.chain if options[:source_type] b[0] = PolymorphicReflection.new(b[0], self) @@ -759,8 +759,8 @@ module ActiveRecord end end - def join_keys(assoc_klass) - source_reflection.join_keys(assoc_klass) + def join_keys(association_klass) + source_reflection.join_keys(association_klass) end # The macro used by the source association @@ -898,10 +898,10 @@ module ActiveRecord end - class PolymorphicReflection < ThroughReflection - def initialize(reflection, prev_reflection) + class PolymorphicReflection < ThroughReflection # :nodoc: + def initialize(reflection, previous_reflection) @reflection = reflection - @prev_reflection = prev_reflection + @previous_reflection = previous_reflection end def klass @@ -920,8 +920,8 @@ module ActiveRecord @reflection.plural_name end - def join_keys(assoc_klass) - @reflection.join_keys(assoc_klass) + def join_keys(association_klass) + @reflection.join_keys(association_klass) end def type @@ -933,13 +933,13 @@ module ActiveRecord end def source_type_info - type = @prev_reflection.foreign_type - source_type = @prev_reflection.options[:source_type] + type = @previous_reflection.foreign_type + source_type = @previous_reflection.options[:source_type] lambda { |object| where(type => source_type) } end end - class RuntimeReflection < PolymorphicReflection + class RuntimeReflection < PolymorphicReflection # :nodoc: attr_accessor :next def initialize(reflection, association) -- cgit v1.2.3