Class: ActiveRecord::PredicateBuilder::AssociationQueryValue
Do not use. This class is for internal use only.
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb |
Class Method Summary
Instance Attribute Summary
- #reflection readonly private
- #value readonly private
Instance Method Summary
- #queries
- #association_route_for(target) private
- #convert_to_id(value, destination_key) private
- #ensure_ids_are_sufficient! private
- #ids(query_value, route) private
- #nil_query private
- #queries_for_array(values) private
- #queries_for_route(query_value, route) private
- #record_or_relation?(target) ⇒ Boolean private
Constructor Details
.new(reflection, value, origin_class) ⇒ AssociationQueryValue
# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 6
def initialize(reflection, value, origin_class) @reflection = reflection @value = value @origin_class = origin_class end
Instance Attribute Details
#reflection (readonly, private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 25
attr_reader :reflection, :value
#value (readonly, private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 25
attr_reader :reflection, :value
Instance Method Details
#association_route_for(target) (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 83
def association_route_for(target) destination_class = case target when Relation target.model when Base target.class else reflection.klass end (@routes ||= {})[destination_class] ||= reflection.association_route(origin_class: @origin_class, destination_class: destination_class) end
#convert_to_id(value, destination_key) (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 99
def convert_to_id(value, destination_key) if value.is_a?(Base) destination_key.value_of(value) elsif value.respond_to?(destination_key.name) value.public_send(destination_key.name) else value end end
#ensure_ids_are_sufficient! (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 39
def ensure_ids_are_sufficient! return if association_route_for(nil). items = value.is_a?(Array) ? value : [value] if items.any? { |item| !item.nil? && !record_or_relation?(item) } raise ArgumentError, "#{reflection.active_record}##{reflection.name} matches on more than one column, " \ "so it must be queried with records or relations rather than ids" end end
#ids(query_value, route) (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 63
def ids(query_value, route) destination_key = route.destination_key case query_value when Relation relation = query_value relation = relation.select(destination_key.name) if relation.select_values.empty? route.destination_fixed_values.each do |column, value| physical_column = relation.model.attribute_aliases[column] || column unless relation.where_values_hash.has_key?(physical_column) relation = relation.where(column => value) end end relation when Array query_value.map { |item| convert_to_id(item, destination_key) } else [convert_to_id(query_value, destination_key)] end end
#nil_query (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 56
def nil_query # Query-constraint columns may still be populated when a reference is # unset, so a nil query should only match against the reference columns. key = association_route_for(nil).reference_origin_key key.where_hash(key.map_value { nil }) end
#queries
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 12
def queries ensure_ids_are_sufficient! if value.nil? [nil_query] elsif value.is_a?(Array) queries_for_array(value) else queries_for_route(value, association_route_for(value)) end end
#queries_for_array(values) (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 27
def queries_for_array(values) if values.none? { |item| item.nil? || record_or_relation?(item) } return queries_for_route(values, association_route_for(nil)) end items_by_route = values.group_by { |item| association_route_for(item) unless item.nil? } nils = items_by_route.delete(nil) queries = items_by_route.flat_map { |route, items| queries_for_route(items, route) } queries << nil_query if nils queries end
#queries_for_route(query_value, route) (private)
[ GitHub ]# File 'activerecord/lib/active_record/relation/predicate_builder/association_query_value.rb', line 49
def queries_for_route(query_value, route) id_list = ids(query_value, route) id_list = id_list.pluck(route.destination_key.name) if route.origin_key.composite? && id_list.is_a?(Relation) route.origin_key.where_clauses(id_list) end