aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2016-02-18 10:47:47 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2016-02-18 10:47:47 -0800
commitfb8d01f1ef7da0a3c8c0173d6c3da59afe9d1ca5 (patch)
tree258d75655ddcd9aacd2df0b74bb6c58404e3de9b /activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
parente4c3225b2c9475ebfac474c7196dec2feb290e5a (diff)
parent3bd9fe1708018e4e82f5d836cc6e047d9d9b5b55 (diff)
downloadrails-fb8d01f1ef7da0a3c8c0173d6c3da59afe9d1ca5.tar.gz
rails-fb8d01f1ef7da0a3c8c0173d6c3da59afe9d1ca5.tar.bz2
rails-fb8d01f1ef7da0a3c8c0173d6c3da59afe9d1ca5.zip
Merge branch 'master' into treewip
* master: (27 commits) move digest cache on to the DetailsKey object remove object `hash` cache [ci skip] fix suggested change-replace 'an' with 'the in Rails engine guide' Missing documentation about hash algorithm option for MessageVerifier [ci skip] set `skip_listen` option to dummy appplication Fix the language in engines guide Add accidentally removed `#` [ci skip] fields_for_style needs to test for AC::Parameters Fix indentation for code block in changelog Remove accidentally duplicated change log title [ci skip] partially revert 69009f4473637a44ade26d954ef5ddea6ff903f2 Remove needless `case_insensitive_comparison` in mysql2 adapter modify to `error` also abort when specify fail fast option Implement ActionController::Parameters#inspect remove unused method Remove unused Journey code Add Action Cable CHANGELOG in release notes [ci skip] Show proper error message when a non-relation object is passed to AR::Relation#or Fix semantics of test names for finish option in batches_test Fix typo ... Conflicts: actionview/lib/action_view/digestor.rb
Diffstat (limited to 'activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb')
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb57
1 files changed, 57 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
new file mode 100644
index 0000000000..b6c6240343
--- /dev/null
+++ b/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb
@@ -0,0 +1,57 @@
+module ActiveRecord
+ class PredicateBuilder
+ class PolymorphicArrayHandler # :nodoc:
+ def initialize(predicate_builder)
+ @predicate_builder = predicate_builder
+ end
+
+ def call(attribute, value)
+ table = value.associated_table
+ queries = value.type_to_ids_mapping.map do |type, ids|
+ { table.association_foreign_type.to_s => type, table.association_foreign_key.to_s => ids }
+ end
+
+ predicates = queries.map { |query| predicate_builder.build_from_hash(query) }
+
+ if predicates.size > 1
+ type_and_ids_predicates = predicates.map { |type_predicate, id_predicate| Arel::Nodes::Grouping.new(type_predicate.and(id_predicate)) }
+ type_and_ids_predicates.inject(&:or)
+ else
+ predicates.first
+ end
+ end
+
+ protected
+
+ attr_reader :predicate_builder
+ end
+
+ class PolymorphicArrayValue # :nodoc:
+ attr_reader :associated_table, :values
+
+ def initialize(associated_table, values)
+ @associated_table = associated_table
+ @values = values
+ end
+
+ def type_to_ids_mapping
+ default_hash = Hash.new { |hsh, key| hsh[key] = [] }
+ values.each_with_object(default_hash) { |value, hash| hash[base_class(value).name] << convert_to_id(value) }
+ end
+
+ private
+
+ def primary_key(value)
+ associated_table.association_primary_key(base_class(value))
+ end
+
+ def base_class(value)
+ value.class.base_class
+ end
+
+ def convert_to_id(value)
+ value._read_attribute(primary_key(value))
+ end
+ end
+ end
+end