From 5180fe2cd8233169935065efe8762bd5d7b2709c Mon Sep 17 00:00:00 2001 From: Ben Toews Date: Tue, 26 Sep 2017 09:29:24 -0600 Subject: allow table name and direction in string order arg --- .../lib/active_record/relation/calculations.rb | 31 ++++++---------------- .../lib/active_record/relation/query_methods.rb | 26 ++++++++++++++++-- 2 files changed, 32 insertions(+), 25 deletions(-) (limited to 'activerecord/lib/active_record/relation') diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 236d36e15f..75795fe493 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -180,14 +180,15 @@ module ActiveRecord end if has_include?(column_names.first) - construct_relation_for_association_calculations.pluck(*column_names) + relation = apply_join_dependency + relation.pluck(*column_names) else - enforce_raw_sql_whitelist(column_names) + enforce_raw_sql_whitelist(column_names, whitelist: allowed_pluck_columns) relation = spawn relation.select_values = column_names.map { |cn| @klass.respond_to_attribute?(cn) ? arel_attribute(cn) : cn } - result = klass.connection.select_all(relation.arel, nil, bound_attributes) + result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) } result.cast_values(klass.attribute_types) end end @@ -202,26 +203,10 @@ module ActiveRecord private - def _pluck(column_names, unsafe_raw) - unrecognized = column_names.reject do |cn| - @klass.respond_to_attribute?(cn) - end - - if loaded? && unrecognized.none? - records.pluck(*column_names) - elsif has_include?(column_names.first) - relation = apply_join_dependency - relation.pluck(*column_names) - elsif unsafe_raw || unrecognized.none? - relation = spawn - relation.select_values = column_names.map { |cn| - @klass.respond_to_attribute?(cn) ? arel_attribute(cn) : cn - } - result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) } - result.cast_values(klass.attribute_types) - else - raise ArgumentError, "Invalid column name: #{unrecognized}" - end + def allowed_pluck_columns + @klass.attribute_names_and_aliases.map do |name| + [name, "#{table_name}.#{name}"] + end.flatten end def has_include?(column_name) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index f3b44d19d6..094e5aa733 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -297,7 +297,11 @@ module ActiveRecord # Same as #order but operates on relation in-place instead of copying. def order!(*args) # :nodoc: - @klass.enforce_raw_sql_whitelist(column_names_from_order_arguments(args)) + @klass.enforce_raw_sql_whitelist( + column_names_from_order_arguments(args), + whitelist: allowed_order_columns + ) + preprocess_order_args(args) self.order_values += args @@ -320,7 +324,11 @@ module ActiveRecord # Same as #reorder but operates on relation in-place instead of copying. def reorder!(*args) # :nodoc: - @klass.enforce_raw_sql_whitelist(column_names_from_order_arguments(args)) + @klass.enforce_raw_sql_whitelist( + column_names_from_order_arguments(args), + whitelist: allowed_order_columns + ) + preprocess_order_args(args) self.reordering_value = true @@ -920,6 +928,20 @@ module ActiveRecord private + def allowed_order_columns + @klass.attribute_names_and_aliases.map do |name| + [name, "#{table_name}.#{name}"].map do |name| + [ + name, + "#{name} asc", + "#{name} ASC", + "#{name} desc", + "#{name} DESC" + ] + end + end.flatten + end + # Extract column names from arguments passed to #order or #reorder. def column_names_from_order_arguments(args) args.flat_map { |arg| arg.is_a?(Hash) ? arg.keys : arg } -- cgit v1.2.3