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

+3


source to share


2 answers


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

.

0


source


To override the default scope, use the unscoped

: method Product.unscoped.hidden

.



The reason this was conditional addition is because the code does exactly what you told it to do: run the default scope, then specify any special conditions.

0


source







All Articles