This project is archived and is in readonly mode.
AR::Base#unscoped inconsistency
Reported by Akira Matsuda | August 16th, 2010 @ 10:15 AM | in 3.1
AR::Base#unscoped shows strange behaviour.
In short, it works unexpectedly on default_scoped model only when
called via method chaining and chains to another named_scope.
Let me show an example. Consider the following model:
% rails g model post title:string body:string author:string published:boolean
class Post < ActiveRecord::Base
default_scope where :published => true
scope :written_by, lambda {|name| where :author => name}
end
Queries are default_scoped like this:
Post.scoped.to_sql
=> SELECT "posts". FROM "posts" WHERE ("posts"."published" = 't')
Post.written_by('DHH').to_sql
=> SELECT "posts". FROM "posts" WHERE ("posts"."published" = 't') AND ("posts"."author" = 'DHH')
and unscoped method works as documented:
Post.unscoped.to_sql
=> SELECT "posts".* FROM "posts"
unscoped + where unscopes the default_scope and adds the where
conditions:
Post.unscoped.where(:author => 'DHH').to_sql
=> SELECT "posts".* FROM "posts" WHERE ("posts"."author" = 'DHH')
it works the same with a named_scope given inside a
block:
Post.unscoped { Post.written_by 'DHH' }.to_sql
=> SELECT "posts".* FROM "posts" WHERE ("posts"."author" = 'DHH')
BUT, the unscoped default_scope comes back to life while unscoped are combined with a named_scope via method chaining.
Post.unscoped.written_by('DHH').to_sql
=> SELECT "posts".* FROM "posts" WHERE ("posts"."published" = 't') AND ("posts"."author" = 'DHH')
Is this intentional or a bug?
Comments and changes to this ticket
-
Neeraj Singh August 16th, 2010 @ 02:26 PM
- Milestone set to 3.x
- State changed from new to open
- Importance changed from to Low
Yes it is a bug.
-
Neeraj Singh August 16th, 2010 @ 02:48 PM
I personally think a design change is needed to fix this issue. In the meantime following code will solve the issue.
Post.unscoped do self.written_by('dhh').to_sql end
-
Cyrille September 2nd, 2010 @ 12:14 PM
Moreover:
class Organization < ActiveRecord::Base default_scope where("organizations.state = 'active'").order("organizations.qs DESC, organizations.title ASC") unscoped do scope :latest, lambda { |num| order("organizations.created_at DESC").where("organizations.state = 'active'").limit(num) } end def self.latest2(num) unscoped.order("organizations.created_at DESC").where("organizations.state = 'active'").limit(num) end end
ruby-1.9.2-p0 > Organization.latest(5).to_sql
=> "SELECTorganizations
.* FROMorganizations
WHERE (organizations.state = 'active') ORDER BY organizations.qs DESC, organizations.title ASC, organizations.created_at DESC LIMIT 5"if the named scope is defined inside the unscoped block it's not working. Whereas the following is working as excepted
ruby-1.9.2-p0 > Organization.latest2(5).to_sql
=> "SELECTorganizations
.* FROMorganizations
WHERE (organizations.state = 'active') ORDER BY organizations.created_at DESC LIMIT 5" -
Neeraj Singh September 3rd, 2010 @ 06:34 PM
- Assigned user set to Neeraj Singh
@Cyrille Personally I think latest is working as expected. The latest scope should not be declared inside unscoped.
I will take another look at this defect but as I remember from my first stab at this issue it is kind of hard to fix without some design change. However now that rails2 is released I will look into it with the possibility of some change in design.
-
Cyrille September 11th, 2010 @ 09:31 AM
@Neeraj
In rails 2 I think you were allowed to do stuff like
with_exclusive_scope do named_scope :most_recent ... named_scope :cheapest ... end
In order to define all named scope that don't require default_scope
So I was wondering what's the equivalent in Rails 3 as you said it's not unscoped do ?
The only way for now I find in order to defined scope that wouldn't apply default_scope is to create class method for them like my previous latest2 example. I just think with_exclusive_scope was DRYer ;)
-
Neeraj Singh September 11th, 2010 @ 01:08 PM
I posted the answer earlier in a comment.
https://rails.lighthouseapp.com/projects/8994/tickets/5386-arbaseun...
-
Santiago Pastorino November 7th, 2010 @ 11:35 AM
- Milestone changed from 3.x to 3.1
- Assigned user changed from Neeraj Singh to Aaron Patterson
-
rails March 29th, 2011 @ 01:00 AM
This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.
Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.
-
rails March 29th, 2011 @ 01:00 AM
- State changed from open to stale
-
Brian Bokor April 26th, 2011 @ 11:59 PM
I dont' have a solution for this issue but I have noticed that in 3.0.5
Doesn't work
scope :latest, unscoped.order()Doesn't work
unscoped doscope :latest, order()
end
Works
def self.latestunscoped.order()
end
Works (although deprecated)
scope :latest, reorder()I'm not sure I'll have time right now to look into fixing but that is what my tests have proven.
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
Referenced by
- 5424 Merging "order" clauses from default_scope and regular scope This issue is already in LH as ticket #5386.
- 5386 AR::Base#unscoped inconsistency https://rails.lighthouseapp.com/projects/8994/tickets/53...