Merge pull request #4282 from edgecase/order_after_reorder

correctly handle order calls after a reorder
This commit is contained in:
Aaron Patterson 2012-01-04 10:12:40 -08:00
commit 34551bf31e
6 changed files with 25 additions and 9 deletions

@ -8,7 +8,7 @@ class Relation
JoinOperation = Struct.new(:relation, :join_class, :on)
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq]
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq]
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation

@ -134,7 +134,7 @@ def first!
def last(*args)
if args.any?
if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
if order_values.empty? && reorder_value.nil?
if order_values.empty?
order("#{primary_key} DESC").limit(*args).reverse
else
to_a.last(*args)
@ -249,7 +249,7 @@ def apply_join_dependency(relation, join_dependency)
end
def construct_limited_ids_condition(relation)
orders = (relation.reorder_value || relation.order_values).map { |val| val.presence }.compact
orders = relation.order_values.map { |val| val.presence }.compact
values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders)
relation = relation.dup

@ -9,7 +9,7 @@ module QueryMethods
:select_values, :group_values, :order_values, :joins_values,
:where_values, :having_values, :bind_values,
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
:from_value, :reorder_value, :reverse_order_value,
:from_value, :reordering_value, :reverse_order_value,
:uniq_value
def includes(*args)
@ -97,7 +97,8 @@ def reorder(*args)
return self if args.blank?
relation = clone
relation.reorder_value = args.flatten
relation.reordering_value = true
relation.order_values = args.flatten
relation
end
@ -263,7 +264,7 @@ def build_arel
arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
order = @reorder_value ? @reorder_value : @order_values
order = @order_values
order = reverse_sql_order(order) if @reverse_order_value
arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?

@ -22,7 +22,7 @@ def merge(r)
end
end
(Relation::MULTI_VALUE_METHODS - [:joins, :where]).each do |method|
(Relation::MULTI_VALUE_METHODS - [:joins, :where, :order]).each do |method|
value = r.send(:"#{method}_values")
merged_relation.send(:"#{method}_values=", merged_relation.send(:"#{method}_values") + value) if value.present?
end
@ -48,7 +48,7 @@ def merge(r)
merged_relation.where_values = merged_wheres
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with]).each do |method|
(Relation::SINGLE_VALUE_METHODS - [:lock, :create_with, :reordering]).each do |method|
value = r.send(:"#{method}_value")
merged_relation.send(:"#{method}_value=", value) unless value.nil?
end
@ -57,6 +57,15 @@ def merge(r)
merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
if (r.reordering_value)
# override any order specified in the original relation
merged_relation.reordering_value = true
merged_relation.order_values = r.order_values
else
# merge in order_values from r
merged_relation.order_values += r.order_values
end
# Apply scope extension modules
merged_relation.send :apply_modules, r.extensions

@ -421,6 +421,12 @@ def test_reorder_overrides_default_scope_order
assert_equal expected, received
end
def test_order_after_reorder_combines_orders
expected = Developer.order('name DESC, id DESC').collect { |dev| [dev.name, dev.id] }
received = Developer.order('name ASC').reorder('name DESC').order('id DESC').collect { |dev| [dev.name, dev.id] }
assert_equal expected, received
end
def test_nested_exclusive_scope
expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary }
received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do

@ -20,7 +20,7 @@ def test_construction
end
def test_single_values
assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq].map(&:to_s).sort,
assert_equal [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq].map(&:to_s).sort,
Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort
end