This project is archived and is in readonly mode.

[PATCH] except doesn't work in different scopes
Reported by 2kan | January 15th, 2011 @ 12:49 AM | in 3.1
Here is an example:
class A < ActiveRecord::Base
  scope :order_by_salary, order("salary DESC")
  scope :reorder_by_name, except(:order).order("name DESC")
end
So this code won't work:
A.order_by_salary.reorder_by_name
Comments and changes to this ticket
- 
            
         
- 
            
         2kan January 15th, 2011 @ 12:55 AM- Assigned user changed from Santiago Pastorino to Aaron Patterson
- Tag changed from activerecord scopes, rails edge, scope to activerecord scopes, rails edge, bug, patch, scope
 
- 
         Santiago Pastorino February 2nd, 2011 @ 06:30 PM- State changed from new to open
- Milestone set to 3.1
- Importance changed from  to Low
 The expression scope :reorder_by_name, except(:order).order("name DESC") is computed at evaluation time. You need to do this ... class A < ActiveRecord::Base scope :order_by_salary, order("salary DESC") scope :reorder_by_name, lambda { except(:order).order("name DESC") } endAnyways seems the code I showed you is not currently working on master with named scopes even though it works if I do ... >> Post.order(:title).to_sql => "SELECT \"posts\".* FROM \"posts\" ORDER BY title" >> Post.order(:title).except(:order).to_sql => "SELECT \"posts\".* FROM \"posts\" " >> Post.order(:title).except(:order).order(:body).to_sql => "SELECT \"posts\".* FROM \"posts\" ORDER BY body"So we need to fix the issue for named scopes. 
- 
            
         Adam Wróbel February 2nd, 2011 @ 11:27 PMI suggest moving order from MULTI_VALUE_METHODS to SINGLE_VALUE_METHODS and overwriting the order array with each merged scope or new call to order(). There's no benefit in using: Employee.order(:division_name).order(:name)over Employee.order(:division_name,:name)And the fact that both of the below calls return Posts by [:created_at,:title] order is just plain misleading: class Post < ActiveRecord::Base default_scope order(:created_at) scope :by_title, order(:title) end Post.order(:title) Post.by_title
- 
            
         2kan February 2nd, 2011 @ 11:50 PMAdam Wróbel, order is a multi value and I can give you a lot of examples from my real apps where you need to use queries like: SELECT * from employers WHERE ORDER BY salary ASC, name ASCHere you sort employers by salary and if salary is equal you sort then by name. It is a common task. And so if we're allow user to write order('salary ASC, name ASC') I think we should allow to write order(:salary).order(:name). 
- 
            
         2kan February 2nd, 2011 @ 11:56 PMAdam Wróbel, i mean that it is not intuitive why we can do: order(:division_name).order(:name)and can't: Employee.order(:division_name,:name)or do something like: class Post < ActiveRecord::Base scope popular, where('rating > 1').order('rating DESC') scope recent, order('created_at DESC') end Post.popular.recent
- 
            
         2kan February 2nd, 2011 @ 11:58 PMOh, sorry, it is 2:57 AM here. In my previous comment we can't do first and can second and so can't do the last example with a Post class. 
- 
            
         Adam Wróbel February 3rd, 2011 @ 12:05 AMAn alternative would be to overwrite on merge, but append on order(). That would be similar to where(:column => value). Multiple where() calls create OR but during a merge only the last one is left. 
- 
            
         Adam Wróbel February 3rd, 2011 @ 12:22 AMI know you specify multiple columns for order, but when I referred to multi and single values I meant values that get merged and values that get overwritten. My suggestion was to overwrite array of order columns from the current scope with array of order columns from the relation being merged in. The Post.popular.recent example makes sense and might be a reason for why none of my suggestions should be used, but then again order is such a simple operation that it's easy to list all the columns you need in one place. Usually I'd just be confused that my last call to order wasn't the one used rather than happy that I was was able to merge two named order scopes. Take this test from rails tests (tests/cases/relations_test.rb): def test_order_using_scoping car1 = CoolCar.order('id DESC').scoping do CoolCar.find(:first, :order => 'id asc') end assert_equal 'zyke', car1.name car2 = FastCar.order('id DESC').scoping do FastCar.find(:first, :order => 'id asc') end assert_equal 'zyke', car2.name endTo me it reads "def test_we_have_a_bug". I mean - I've specified the order I want right there - in the call to find() - why do you do it reverse, rails? 
- 
            
         2kan February 3rd, 2011 @ 04:34 PMSantiago Pastorino, Yes this code computes at evaluation time, but it doesn't matter. I think that there is no reason (point me if i'm wrong) to allow user to use except only inside lambdas. I understand that I need to use lambda when I use Time.now or something but here I need some additional knowledge about how except, order, where and etc works inside rails. I don't think that it is good. I've added to my patch test with scope with lambda like: lambda { except(:order).order("name DESC") }and test passes. How it works and why I think we can calculate except at evaluation time. A've added a flag into the Relation that it is except and store what we want to except, so when we merge relations when calling the scopes we can figure out that we need to except some values. Please, point me if I made a mistake somewhere. 
- 
            
         2kan March 21st, 2011 @ 01:44 PMOops, I've found that my last uploaded patch wasn't good enough (I've uploaded the wrong diff, sorry). Here is the correct one. 
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Attachments
Referenced by
- 
         1812 
          default_scope can't take procs
        Known issues: this ticket, ticket #6011 (which
as I under... 1812 
          default_scope can't take procs
        Known issues: this ticket, ticket #6011 (which
as I under...
- 
         6011 
          except(:order).order(...) is not working in scopes
        Santiago, yes it is. (Just checked). Somehow (not sure) i... 6011 
          except(:order).order(...) is not working in scopes
        Santiago, yes it is. (Just checked). Somehow (not sure) i...
 2kan
      2kan
 Aaron Patterson
      Aaron Patterson
 Jeremy Kemper
      Jeremy Kemper
 Piotr Sarnacki
      Piotr Sarnacki
 Santiago Pastorino
      Santiago Pastorino