diff options
Diffstat (limited to 'activerecord/lib/active_record/relation')
4 files changed, 29 insertions, 15 deletions
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index a7d2f4bd24..df27318678 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -165,7 +165,9 @@ module ActiveRecord if has_include?(column_names.first) construct_relation_for_association_calculations.pluck(*column_names) else - result = klass.connection.select_all(select(column_names).arel, nil, bind_values) + relation = spawn + relation.select_values = column_names + result = klass.connection.select_all(relation.arel, nil, bind_values) columns = result.columns.map do |key| klass.column_types.fetch(key) { result.column_types.fetch(key) { diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index ab8b36c8ab..dbfa92bbbd 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -1,3 +1,4 @@ +require 'thread' module ActiveRecord module Delegation # :nodoc: @@ -6,6 +7,8 @@ module ActiveRecord delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass + @@delegation_mutex = Mutex.new + def self.delegate_to_scoped_klass(method) if method.to_s =~ /\A[a-zA-Z_]\w*[!?]?\z/ module_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -32,13 +35,28 @@ module ActiveRecord def method_missing(method, *args, &block) if @klass.respond_to?(method) - ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) + end + end + scoping { @klass.send(method, *args, &block) } elsif Array.method_defined?(method) - ::ActiveRecord::Delegation.delegate method, :to => :to_a + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate method, :to => :to_a + end + end + to_a.send(method, *args, &block) elsif arel.respond_to?(method) - ::ActiveRecord::Delegation.delegate method, :to => :arel + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate method, :to => :arel + end + end + arel.send(method, *args, &block) else super diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 99c2f45bc8..af67b2ba6c 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/hash/indifferent_access' - module ActiveRecord module FinderMethods # Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). @@ -225,7 +223,7 @@ module ActiveRecord def construct_limited_ids_condition(relation) orders = relation.order_values.map { |val| val.presence }.compact - values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) + values = @klass.connection.distinct("#{quoted_table_name}.#{primary_key}", orders) relation = relation.dup @@ -234,8 +232,6 @@ module ActiveRecord end def find_with_ids(*ids) - return to_a.find { |*block_args| yield(*block_args) } if block_given? - expects_array = ids.first.kind_of?(Array) return ids.first if expects_array && ids.first.empty? diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 4fdc296c7e..0817bb6d81 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -218,7 +218,6 @@ module ActiveRecord # Like #order, but modifies relation in place. def order!(*args) args.flatten! - validate_order_args args references = args.reject { |arg| Arel::Node === arg } @@ -245,7 +244,6 @@ module ActiveRecord # Like #reorder, but modifies relation in place. def reorder!(*args) args.flatten! - validate_order_args args self.reordering_value = true @@ -796,7 +794,7 @@ module ActiveRecord def reverse_sql_order(order_query) order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty? - order_query.map do |o| + order_query.flat_map do |o| case o when Arel::Nodes::Ordering o.reverse @@ -814,7 +812,7 @@ module ActiveRecord else o end - end.flatten + end end def array_of_strings?(o) @@ -825,7 +823,7 @@ module ActiveRecord orders = order_values orders = reverse_sql_order(orders) if reverse_order_value - orders = orders.uniq.reject(&:blank?).map do |order| + orders = orders.uniq.reject(&:blank?).flat_map do |order| case order when Symbol table[order].asc @@ -834,7 +832,7 @@ module ActiveRecord else order end - end.flatten + end arel.order(*orders) unless orders.empty? end |