From 50a8cdf0e2cff604b0361a370afc8becf2579d94 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Mon, 19 Jan 2015 15:09:47 -0700 Subject: Move `create_binds` over to the `PredicateBuilder` I'm looking to introduce a `WhereClause` class to handle most of this logic, and this method will eventually move over to there. However, this intermediate refactoring should make that easier to do. --- .../active_record/relation/predicate_builder.rb | 26 +++++++++++++++-- .../lib/active_record/relation/query_methods.rb | 33 +--------------------- activerecord/lib/active_record/table_metadata.rb | 6 ++++ 3 files changed, 31 insertions(+), 34 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 567efce8ae..f1cb4e1bee 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -28,6 +28,25 @@ module ActiveRecord expand_from_hash(attributes) end + def create_binds(attributes) + result = attributes.dup + binds = [] + + attributes.each do |column_name, value| + case value + when String, Integer, ActiveRecord::StatementCache::Substitute + result[column_name] = Arel::Nodes::BindParam.new + binds.push([table.column(column_name), value]) + when Hash + attrs, bvs = associated_predicate_builder(column_name).create_binds(value) + result[column_name] = attrs + binds += bvs + end + end + + [result, binds] + end + def expand(column, value) # Find the foreign key when using queries such as: # Post.where(author: author) @@ -80,8 +99,7 @@ module ActiveRecord attributes.flat_map do |key, value| if value.is_a?(Hash) - builder = self.class.new(table.associated_table(key)) - builder.expand_from_hash(value) + associated_predicate_builder(key).expand_from_hash(value) else expand(key, value) end @@ -90,6 +108,10 @@ module ActiveRecord private + def associated_predicate_builder(association_name) + self.class.new(table.associated_table(association_name)) + end + def convert_dot_notation_to_hash(attributes) dot_notation = attributes.keys.select { |s| s.include?(".") } diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 0e50534d47..c3c1b6c961 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -945,7 +945,7 @@ module ActiveRecord when Hash opts = predicate_builder.resolve_column_aliases(opts) - tmp_opts, bind_values = create_binds(opts) + tmp_opts, bind_values = predicate_builder.create_binds(opts) self.bind_values += bind_values attributes = @klass.send(:expand_hash_conditions_for_aggregates, tmp_opts) @@ -957,37 +957,6 @@ module ActiveRecord end end - def create_binds(opts) - bindable, non_binds = opts.partition do |column, value| - value.is_a?(String) || - value.is_a?(Integer) || - value.is_a?(ActiveRecord::StatementCache::Substitute) - end - - association_binds, non_binds = non_binds.partition do |column, value| - value.is_a?(Hash) && association_for_table(column) - end - - new_opts = {} - binds = [] - - bindable.each do |(column,value)| - binds.push [@klass.columns_hash[column.to_s], value] - new_opts[column] = connection.substitute_at(column) - end - - association_binds.each do |(column, value)| - association_relation = association_for_table(column).klass.send(:relation) - association_new_opts, association_bind = association_relation.send(:create_binds, value) - new_opts[column] = association_new_opts - binds += association_bind - end - - non_binds.each { |column,value| new_opts[column] = value } - - [new_opts, binds] - end - def association_for_table(table_name) table_name = table_name.to_s @klass._reflect_on_association(table_name) || diff --git a/activerecord/lib/active_record/table_metadata.rb b/activerecord/lib/active_record/table_metadata.rb index 11e33e8dfe..31a40adb67 100644 --- a/activerecord/lib/active_record/table_metadata.rb +++ b/activerecord/lib/active_record/table_metadata.rb @@ -22,6 +22,12 @@ module ActiveRecord arel_table[column_name] end + def column(column_name) + if klass + klass.columns_hash[column_name.to_s] + end + end + def associated_with?(association_name) klass && klass._reflect_on_association(association_name) end -- cgit v1.2.3