I have a default scope on products due to information security constraints.
class Product < ActiveRecord::Base
has_many :photos
default_scope where('visible = 1')
end
In my associated Photo model, however, I also have to find products that should not be visible.
class Photo < ActiveRecord::Base
belongs_to :product
end
my_photo.product
In other cases, I can use unscoped in order to bypass the default_scope, e.g. in Product.unscoped.find_by_title('abc')
. However:
How to remove the scope when using associations of a record?
my_photo.unscoped.product
does not make sense as my_photo does not have a method called unscoped
. Neither does my_photo.product.unscoped
make sense as my_photo.product
may already be nil.
Another option is to override the getter method and unscope super:
I ran into the same situation where I had one associated model that needed to be unscoped, but in almost every other case it needed the default scope. This should save you the extra calls to unscoped if you are using the assocation getter in more than one place.
In Rails 4 you can use the association with an explicit unscope of the undesirable filter i.e.
my_photo.product.unscope(where: :visible)
I'm probably a bit late to the party, but some time ago I found myself in the same situation and I wrote a gem to do this easily: unscoped_associations.
Usage:
Support for:
Polymorphic associations are also supported.
If you need for a specific association to always be unscoped, you can unscope it when defining the association:
For some reason, the specific
where
key wasn't loading correctly for me, so I just unscoped the entirewhere
, which is another option that happens to work out in my case:The other answers are worth looking at too, but this is another option for Rails 4.1+.
It's not on the main topic but on your problem with ActiveRecord#becomes: We (hopefully) fixed it with an initializer
https://gist.github.com/2478161
Oh. I fooled myself. Thought the following would not work... but it does:
Notice that you have to call unscoped on the model with the
default_scope
that should be bypassed.Also, inheritance has to be respected. If you have
class InsuranceProduct < Product
andclass FinancialProduct < Product
and adefault_scope
inProduct
, all of the following two combinations will work:However, the following will not work although the scope is defined in
Product
:I guess that's another quirk of STI in Ruby / Rails.