Skip to content
This repository
Browse code

AR::Relation#order: make new order prepend old one

    User.order("name asc").order("created_at desc")
    # SELECT * FROM users ORDER BY created_at desc, name asc

This also affects order defined in `default_scope` or any kind of associations.
  • Loading branch information...
commit 92641efeecae0910c6292c0c6bf071197b24e63d 1 parent 10cdeb8
Bogdan Gusiev authored July 31, 2012
9  activerecord/CHANGELOG.md
Source Rendered
... ...
@@ -1,5 +1,14 @@
1 1
 ## Rails 4.0.0 (unreleased) ##
2 2
 
  3
+*   AR::Relation#order: make new order prepend old one.
  4
+
  5
+        User.order("name asc").order("created_at desc")
  6
+        # SELECT * FROM users ORDER BY created_at desc, name asc
  7
+
  8
+    This also affects order defined in `default_scope` or any kind of associations.
  9
+
  10
+    *Bogdan Gusiev*
  11
+
3 12
 *   `Model.all` now returns an `ActiveRecord::Relation`, rather than an
4 13
     array of records. Use `Model.to_a` or `Relation#to_a` if you really
5 14
     want an array.
2  activerecord/lib/active_record/relation/finder_methods.rb
@@ -311,7 +311,7 @@ def find_first
311 311
         @records.first
312 312
       else
313 313
         @first ||=
314  
-          if order_values.empty? && primary_key
  314
+          if with_default_scope.order_values.empty? && primary_key
315 315
             order(arel_table[primary_key].asc).limit(1).to_a.first
316 316
           else
317 317
             limit(1).to_a.first
4  activerecord/lib/active_record/relation/query_methods.rb
@@ -214,7 +214,7 @@ def order!(*args)
214 214
       references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact!
215 215
       references!(references) if references.any?
216 216
 
217  
-      self.order_values += args
  217
+      self.order_values = args + self.order_values
218 218
       self
219 219
     end
220 220
 
@@ -226,7 +226,7 @@ def order!(*args)
226 226
     #
227 227
     #   User.order('email DESC').reorder('id ASC').order('name ASC')
228 228
     #
229  
-    # generates a query with 'ORDER BY id ASC, name ASC'.
  229
+    # generates a query with 'ORDER BY name ASC, id ASC'.
230 230
     def reorder(*args)
231 231
       args.blank? ? self : spawn.reorder!(*args)
232 232
     end
4  activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -513,9 +513,9 @@ def test_dynamic_find_should_respect_association_order
513 513
     assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
514 514
   end
515 515
 
516  
-  def test_find_should_append_to_association_order
  516
+  def test_find_should_prepend_to_association_order
517 517
     ordered_developers = projects(:active_record).developers.order('projects.id')
518  
-    assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
  518
+    assert_equal ['projects.id', 'developers.name desc, developers.id desc'], ordered_developers.order_values
519 519
   end
520 520
 
521 521
   def test_dynamic_find_all_should_respect_readonly_access
4  activerecord/test/cases/associations/has_many_associations_test.rb
@@ -231,9 +231,9 @@ def test_find_many_with_merged_options
231 231
     assert_equal 2, companies(:first_firm).limited_clients.limit(nil).to_a.size
232 232
   end
233 233
 
234  
-  def test_find_should_append_to_association_order
  234
+  def test_find_should_prepend_to_association_order
235 235
     ordered_clients =  companies(:first_firm).clients_sorted_desc.order('companies.id')
236  
-    assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
  236
+    assert_equal ['companies.id', 'id DESC'], ordered_clients.order_values
237 237
   end
238 238
 
239 239
   def test_dynamic_find_should_respect_association_order
8  activerecord/test/cases/relation_scoping_test.rb
@@ -385,7 +385,7 @@ def test_default_scope_with_multiple_calls
385 385
   end
386 386
 
387 387
   def test_scope_overwrites_default
388  
-    expected = Developer.all.merge!(:order => 'salary DESC, name DESC').to_a.collect { |dev| dev.name }
  388
+    expected = Developer.all.merge!(:order => ' name DESC, salary DESC').to_a.collect { |dev| dev.name }
389 389
     received = DeveloperOrderedBySalary.by_name.to_a.collect { |dev| dev.name }
390 390
     assert_equal expected, received
391 391
   end
@@ -397,13 +397,13 @@ def test_reorder_overrides_default_scope_order
397 397
   end
398 398
 
399 399
   def test_order_after_reorder_combines_orders
400  
-    expected = Developer.order('name DESC, id DESC').collect { |dev| [dev.name, dev.id] }
  400
+    expected = Developer.order('id DESC, name DESC').collect { |dev| [dev.name, dev.id] }
401 401
     received = Developer.order('name ASC').reorder('name DESC').order('id DESC').collect { |dev| [dev.name, dev.id] }
402 402
     assert_equal expected, received
403 403
   end
404 404
 
405  
-  def test_order_in_default_scope_should_prevail
406  
-    expected = Developer.all.merge!(:order => 'salary desc').to_a.collect { |dev| dev.salary }
  405
+  def test_order_in_default_scope_should_not_prevail
  406
+    expected = Developer.all.merge!(:order => 'salary').to_a.collect { |dev| dev.salary }
407 407
     received = DeveloperOrderedBySalary.all.merge!(:order => 'salary').to_a.collect { |dev| dev.salary }
408 408
     assert_equal expected, received
409 409
   end
10  activerecord/test/cases/relations_test.rb
@@ -165,7 +165,7 @@ def test_finding_last_with_arel_order
165 165
   end
166 166
 
167 167
   def test_finding_with_order_concatenated
168  
-    topics = Topic.order('author_name').order('title')
  168
+    topics = Topic.order('title').order('author_name')
169 169
     assert_equal 4, topics.to_a.size
170 170
     assert_equal topics(:fourth).title, topics.first.title
171 171
   end
@@ -1068,20 +1068,20 @@ def test_order_by_relation_attribute
1068 1068
   end
1069 1069
 
1070 1070
   def test_default_scope_order_with_scope_order
1071  
-    assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
1072  
-    assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
  1071
+    assert_equal 'honda', CoolCar.order_using_new_style.limit(1).first.name
  1072
+    assert_equal 'honda', FastCar.order_using_new_style.limit(1).first.name
1073 1073
   end
1074 1074
 
1075 1075
   def test_order_using_scoping
1076 1076
     car1 = CoolCar.order('id DESC').scoping do
1077 1077
       CoolCar.all.merge!(:order => 'id asc').first
1078 1078
     end
1079  
-    assert_equal 'zyke', car1.name
  1079
+    assert_equal 'honda', car1.name
1080 1080
 
1081 1081
     car2 = FastCar.order('id DESC').scoping do
1082 1082
       FastCar.all.merge!(:order => 'id asc').first
1083 1083
     end
1084  
-    assert_equal 'zyke', car2.name
  1084
+    assert_equal 'honda', car2.name
1085 1085
   end
1086 1086
 
1087 1087
   def test_unscoped_block_style
9  guides/source/active_record_querying.textile
Source Rendered
@@ -492,7 +492,7 @@ This code will generate SQL like this:
492 492
 SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
493 493
 </sql>
494 494
 
495  
-h3. Ordering
  495
+h3(#ordering). Ordering
496 496
 
497 497
 To retrieve records from the database in a specific order, you can use the +order+ method.
498 498
 
@@ -518,6 +518,13 @@ Client.order("orders_count ASC, created_at DESC")
518 518
 Client.order("orders_count ASC", "created_at DESC")
519 519
 </ruby>
520 520
 
  521
+If you want to call +order+ multiple times e.g. in different context, new order will prepend previous one
  522
+
  523
+<ruby>
  524
+Client.order("orders_count ASC").order("created_at DESC")
  525
+# SELECT * FROM clients ORDER BY created_at DESC, orders_count ASC
  526
+</ruby>
  527
+
521 528
 h3. Selecting Specific Fields
522 529
 
523 530
 By default, <tt>Model.find</tt> selects all the fields from the result set using +select *+.
2  guides/source/upgrading_ruby_on_rails.textile
Source Rendered
@@ -42,6 +42,8 @@ h4(#active_record4_0). Active Record
42 42
 
43 43
 The <tt>delete</tt> method in collection associations can now receive <tt>Fixnum</tt> or <tt>String</tt> arguments as record ids, besides records, pretty much like the <tt>destroy</tt> method does. Previously it raised <tt>ActiveRecord::AssociationTypeMismatch</tt> for such arguments. From Rails 4.0 on <tt>delete</tt> automatically tries to find the records matching the given ids before deleting them.
44 44
 
  45
+Rails 4.0 has changed how orders get stacked in +ActiveRecord::Relation+. In previous versions of rails new order was applied after previous defined order. But this is no long true. Check "ActiveRecord Query guide":active_record_querying.html#ordering for more information.
  46
+
45 47
 h4(#active_model4_0). Active Model
46 48
 
47 49
 Rails 4.0 has changed how errors attach with the <tt>ActiveModel::Validations::ConfirmationValidator</tt>. Now when confirmation validations fail the error will be attached to <tt>:#{attribute}_confirmation</tt> instead of <tt>attribute</tt>.

0 notes on commit 92641ef

Please sign in to comment.
Something went wrong with that request. Please try again.