This project is archived and is in readonly mode.
without_exclusive_scope and default_scope issues
Reported by Conrad Taylor | July 25th, 2009 @ 05:55 AM | in 3.x
I'm seeing the following issues with both without_exclusive_scope and default_scope in Rails 2.3.3. For example, given the following:
class Message < ActiveRecord::Base
default_scope :conditions => { :ignored => false }, :order => "rating DESC"
named_scope :positive, :conditions => { :rating => 'positive' }
named_scope :neutral, :conditions => { :rating => 'neutral' }
named_scope :negative, :conditions => { :rating => 'negative' }
named_scope :ignored, :conditions => { :ignored => true }
end
In the console,
> Message.ignored
=> SELECT * FROM "messages" WHERE ("messages"."ignored" = 'f') ORDER BY rating DESC
Next, when trying to use the 'with_exclusive_scope method, the following message is generated:
>> Message.with_exclusive_scope { find( :all ) }
NoMethodError: protected method `with_exclusive_scope' called for #<Class:0x793538>
from /opt/local/lib/ruby/gems/1.9.1/gems/activerecord-2.3.3/lib/active_record/base.rb:1959:in `method_missing'
from (irb):9
from /opt/local/bin/irb:12:in `<main>'
Comments and changes to this ticket
-
Matt Jones July 26th, 2009 @ 12:47 AM
As to the second half, with_exclusive_scope was made protected along with with_scope a while back. You're probably better off wrapping the with_exclusive_scope call inside a model method.
There's definitely something weird going on with the first case - if you create a second model class, identical except for the default scope and try:
MessageWithoutDefault.scoped(:conditions => { :ignored => false }).ignored
I'm investigating and will post an update (hopefully) soon.
-
Matt Jones July 26th, 2009 @ 03:38 AM
On further investigation, here's the situation:
Chaining two named_scopes does something (somewhat) unexpected - they nest in the reverse order.
In other words, this:
MessageWithoutDefault.scoped(:conditions => { :ignored => false }).ignored.all
MessageWithoutDefault.with_scope([PARAMS FOR IGNORED]) do MessageWithoutDefault.with_scope([PARAMS FOR IGNORED => FALSE]) do
MessageWithoutDefault.find(:all)
end end
MessageWithoutDefault.with_scope([PARAMS FOR DEFAULT SCOPE]) do # NOTE: not actually executed - default scope is inserted differently MessageWithoutDefault.with_scope([PARAMS FOR IGNORED]) do
MessageWithoutDefault.with_scope([PARAMS FOR IGNORED => FALSE]) do MessageWithoutDefault.find(:all) end
end endThere's a bigger issue here, though; with_scope tends to flatten Hash conditions to strings, making it hard to override :conditions in default_scope. For instance, doing this:
Message.ignored.scoped(:conditions => ['rating LIKE ?', 'p%'])
=> SELECT * FROM "messages" WHERE ((("messages"."ignored" = 'f') AND (rating LIKE 'p%')) AND ("messages"."ignored" = 't')) ORDER BY rating DESC
Maybe some of the ActiveRelation stuff going on in the GSoC will help with this?
-
Chuck Hoffman November 24th, 2009 @ 05:24 PM
I seem to be experiencing this same issue. Here's a description I posted earlier at https://gist.github.com/ea8322b9c7383835101c
class MyModel < ActiveRecord::Base belongs_to :parent_model # ... default_scope :conditions => { :is_hidden => false } named_scope :primary, :conditions => { :is_primary => true }, :order => "position" named_scope :secondary, :conditions => { :is_primary => false }, :order => "position" p = ParentModel.first p.my_models #<-- works fine p.my_models.primary #<-- works fine p.my_models.secondary #<-- works fine # what I need is a finder method/scope to find on the condition { :is_hidden => true } # preferably one that also works through the belongs_to :parent association. # here are some things I've tried: named_scope :hidden, :conditions => { :is_hidden => true } # p.my_models.hidden seems to end up acting identically to p.my_models.secondary in this # case. Might also be the case if called on the class as MyModel.hidden # (see https://rails.lighthouseapp.com/projects/8994/tickets/2953-without_exclusive_scope-and-default_scope-issues) def self.find_with_hidden(*args) self.with_exclusive_scope { find(*args) } end # here I'm adapting the find_with_destroyed method shown on # http://blog.semanticart.com/using_default_scope_to_recreate_acts_as_paranoid/ # unfortunately, it won't work correctly through an association: calling # p.my_models.find_with_hidden(:all) returns all MyModels, not just those that # belong to p -- in other words, with_exclusive_scope is TOO exclusive because # it loses the association scope. # But if I try passing the above more conditions to get the results I want, I get errors: MyModel.find_with_hidden(:conditions => { :parent_model_id => 1 }) # gets this error: # ActiveRecord::RecordNotFound: Couldn't find MyModel without an ID # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1567:in `find_from_ids' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:616:in `find' # from /home/chuck/projects/diyseo/app/models/page_keyword.rb:34:in `find_with_business_name' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2143:in `with_scope' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2151:in `with_exclusive_scope' # from /home/chuck/projects/diyseo/app/models/page_keyword.rb:34:in `find_with_business_name' MyModel.find_with_hidden(:conditions => { :is_hidden => true }) # ActiveRecord::RecordNotFound: Couldn't find MyModel without an ID # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1567:in `find_from_ids' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:616:in `find' # from /home/chuck/projects/diyseo/app/models/page_keyword.rb:34:in `find_with_business_name' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2143:in `with_scope' # from /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2151:in `with_exclusive_scope' # from /home/chuck/projects/diyseo/app/models/page_keyword.rb:34:in `find_with_business_name' # Likewise if I try calling the above from an instance method on MyModel like this: def self.hidden_for(parent) MyModel.find_with_hidden(:conditions => { :parent_model_id => parent.id, :is_hidden => true }) end # calling: p.my_models.hidden_for(p) # or: MyModel.hidden_for(p) # both result in the "Couldn't find MyModel without an ID" error above
-
Rohit Arondekar October 9th, 2010 @ 04:01 AM
- State changed from new to stale
- Importance changed from to
Marking ticket as stale. If this is still an issue please leave a comment with suggested changes, creating a patch with tests, rebasing an existing patch or just confirming the issue on a latest release or master/branches.
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>