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`
This commit is contained in:
parent
9b366b95f9
commit
08acb4bccb
@ -131,8 +131,6 @@ def next_chain_scope(scope, table, reflection, connection, assoc_klass, foreign_
|
|||||||
|
|
||||||
def add_constraints(scope, owner, assoc_klass, refl, tracker)
|
def add_constraints(scope, owner, assoc_klass, refl, tracker)
|
||||||
chain = refl.chain
|
chain = refl.chain
|
||||||
scope_chain = refl.scope_chain
|
|
||||||
connection = tracker.connection
|
|
||||||
|
|
||||||
tables = construct_tables(chain, assoc_klass, refl, tracker)
|
tables = construct_tables(chain, assoc_klass, refl, tracker)
|
||||||
|
|
||||||
@ -140,6 +138,7 @@ def add_constraints(scope, owner, assoc_klass, refl, tracker)
|
|||||||
table = tables.last
|
table = tables.last
|
||||||
scope = last_chain_scope(scope, table, owner_reflection, owner, connection, assoc_klass)
|
scope = last_chain_scope(scope, table, owner_reflection, owner, connection, assoc_klass)
|
||||||
|
|
||||||
|
# chain.first always == refl
|
||||||
chain.each_with_index do |reflection, i|
|
chain.each_with_index do |reflection, i|
|
||||||
table, foreign_table = tables.shift, tables.first
|
table, foreign_table = tables.shift, tables.first
|
||||||
|
|
||||||
@ -151,9 +150,11 @@ def add_constraints(scope, owner, assoc_klass, refl, tracker)
|
|||||||
is_first_chain = i == 0
|
is_first_chain = i == 0
|
||||||
klass = is_first_chain ? assoc_klass : reflection.klass
|
klass = is_first_chain ? assoc_klass : reflection.klass
|
||||||
|
|
||||||
|
items = reflection.constraints
|
||||||
|
|
||||||
# Exclude the scope of the association itself, because that
|
# Exclude the scope of the association itself, because that
|
||||||
# was already merged in the #scope method.
|
# was already merged in the #scope method.
|
||||||
scope_chain[i].each do |scope_chain_item|
|
items.each do |scope_chain_item|
|
||||||
item = eval_scope(klass, scope_chain_item, owner)
|
item = eval_scope(klass, scope_chain_item, owner)
|
||||||
|
|
||||||
if scope_chain_item == refl.scope
|
if scope_chain_item == refl.scope
|
||||||
|
@ -161,7 +161,12 @@ def source_macro
|
|||||||
|
|
||||||
macro
|
macro
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def constraints
|
||||||
|
scope ? [scope] : []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Base class for AggregateReflection and AssociationReflection. Objects of
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
||||||
# AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
|
# AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
|
||||||
#
|
#
|
||||||
@ -697,13 +702,59 @@ def through_reflection
|
|||||||
def chain
|
def chain
|
||||||
@chain ||= begin
|
@chain ||= begin
|
||||||
a = source_reflection.chain
|
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 = a + b
|
||||||
chain[0] = self # Use self so we don't lose the information from :source_type
|
chain[0] = self # Use self so we don't lose the information from :source_type
|
||||||
chain
|
chain
|
||||||
end
|
end
|
||||||
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:
|
# Consider the following example:
|
||||||
#
|
#
|
||||||
# class Person
|
# class Person
|
||||||
@ -855,6 +906,12 @@ def check_validity!
|
|||||||
check_validity_of_inverse!
|
check_validity_of_inverse!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def constraints
|
||||||
|
scope_chain = source_reflection.constraints
|
||||||
|
scope_chain << scope if scope
|
||||||
|
scope_chain
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def actual_source_reflection # FIXME: this is a horrible name
|
def actual_source_reflection # FIXME: this is a horrible name
|
||||||
|
Loading…
Reference in New Issue
Block a user