Completing an ActiveRecord and default_scope condition
Is there a way to override the default scope or previous scope in a where condition? (Apart from restructuring the model do not use default_scope
or unscoped)
Also, what is the reason why it works the way it does? It feels like this isn't the most anticipated or intuitive approach.
Sample:
class Product < ActiveRecord::Base
default_scope -> { visible }
scope :visible, -> { where(visible: true) }
scope :hidden, -> { where(visible: false) }
end
When I do this:
Product.hidden
The generated sql tries to match two values:
WHERE "products"."visible" = 't' AND "products"."visible" = 'f'
It's the same without default_scope:
class Product < ActiveRecord::Base
scope :visible, -> { where(visible: true) }
scope :hidden, -> { where(visible: false) }
end
When I do this:
Product.visible.where(visible: false)
Or when I do this:
Product.visible.hidden
The generated sql tries to match two values:
WHERE "products"."visible" = 't' AND "products"."visible" = 'f'
I did it with a complete test case: https://gist.github.com/mmontossi/dcf71457e98a169c28a5
This is an issue when I first asked this thinking it was a bug: https://github.com/rails/rails/issues/20907#issuecomment-122131096
source to share
There is only one thing you need to know about default_scope
, and that is: don't use it.
default_scope
- it's like a medicine. Itβs great at first and everything seems easier, but over time you realize that it was a bad idea to use it. By then, it's too late and you have to deal with the consequences forever. OK, that's not entirely true: you can simply discontinue use default_scope
and rewrite your controllers to explicitly call real-world scopes, which is what you should have done in the first place, because that way it is obvious which data is being retrieved and in a way that is less confusing for other developers ( including the future you will forget to use default_scope
). So default_scope
not as bad as getting on drugs. This is sometimes the case.
Just say no to default_scope
.
source to share