diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-12-26 14:44:48 -0700 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-12-26 14:44:48 -0700 |
commit | 3bbe88ecd7c6a21e01c4730fd6d2034338b9e034 (patch) | |
tree | 9fe6bf0909f1aa56536d9b1a0096bb535ebc83e5 /activerecord | |
parent | 392a453b10abad60432f2612000f306de55b7d1a (diff) | |
download | rails-3bbe88ecd7c6a21e01c4730fd6d2034338b9e034.tar.gz rails-3bbe88ecd7c6a21e01c4730fd6d2034338b9e034.tar.bz2 rails-3bbe88ecd7c6a21e01c4730fd6d2034338b9e034.zip |
Refactor association handling in `PredicateBuilder`
I'm attempting to remove `klass` as a dependency of the predicate
builder, in favor of an object that better represents what we're using
it for. The only part of this which doesn't fit nicely into that picture
is the check for an association being polymorphic. Since I'm not yet
sure what that is going to look like, I've moved this logic into another
class in an attempt to separate things that will change from things that
won't.
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/relation/predicate_builder.rb | 25 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb | 57 |
2 files changed, 61 insertions, 21 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 61db27d150..b0a4f27049 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -1,6 +1,7 @@ module ActiveRecord class PredicateBuilder # :nodoc: require 'active_record/relation/predicate_builder/array_handler' + require 'active_record/relation/predicate_builder/association_query_handler' require 'active_record/relation/predicate_builder/base_handler' require 'active_record/relation/predicate_builder/basic_object_handler' require 'active_record/relation/predicate_builder/class_handler' @@ -18,6 +19,7 @@ module ActiveRecord register_handler(Range, RangeHandler.new) register_handler(Relation, RelationHandler.new) register_handler(Array, ArrayHandler.new(self)) + register_handler(AssociationQueryValue, AssociationQueryHandler.new(self)) end def resolve_column_aliases(hash) @@ -36,35 +38,16 @@ module ActiveRecord end def expand(column, value) - queries = [] - # Find the foreign key when using queries such as: # Post.where(author: author) # # For polymorphic relationships, find the foreign key and type: # PriceEstimate.where(estimate_of: treasure) if klass && reflection = klass._reflect_on_association(column) - if reflection.polymorphic? && base_class = polymorphic_base_class_from_value(value) - queries << build(table[reflection.foreign_type], base_class.name) - end - - column = reflection.foreign_key + value = AssociationQueryValue.new(reflection, value) end - queries << build(table[column], value) - queries - end - - def polymorphic_base_class_from_value(value) - case value - when Relation - value.klass.base_class - when Array - val = value.compact.first - val.class.base_class if val.is_a?(Base) - when Base - value.class.base_class - end + build(table[column], value) end def self.references(attributes) diff --git a/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb new file mode 100644 index 0000000000..bda2c02a10 --- /dev/null +++ b/activerecord/lib/active_record/relation/predicate_builder/association_query_handler.rb @@ -0,0 +1,57 @@ +module ActiveRecord + class PredicateBuilder + class AssociationQueryHandler # :nodoc: + def initialize(predicate_builder) + @predicate_builder = predicate_builder + end + + def call(attribute, value) + queries = {} + + if value.base_class + queries[value.association.foreign_type] = value.base_class.name + end + + queries[value.association.foreign_key] = value.ids + predicate_builder.build_from_hash(queries) + end + + protected + + attr_reader :predicate_builder + end + + class AssociationQueryValue # :nodoc: + attr_reader :association, :value + + def initialize(association, value) + @association = association + @value = value + end + + def ids + value + end + + def base_class + if association.polymorphic? + @base_class ||= polymorphic_base_class_from_value + end + end + + private + + def polymorphic_base_class_from_value + case value + when Relation + value.klass.base_class + when Array + val = value.compact.first + val.class.base_class if val.is_a?(Base) + when Base + value.class.base_class + end + end + end + end +end |