Why is using the rails default_scope often recommend against?

后端 未结 5 2236
执笔经年
执笔经年 2020-11-28 03:59

Everywhere on the internet people mention that using the rails default_scope is a bad idea, and the top hits for default_scope on stackoverflow are

相关标签:
5条回答
  • 2020-11-28 04:18

    For me is not a bad idea but must be used with caution!. There is a case where I always wanted to hide certain records when a field is set.

    1. Preferably the default_scope must match with the DB default value (e.g: { where(hidden_id: nil) })
    2. When you are totally sure you want to show those records, there is always the unscoped method that will avoid your default_scope

    So it will depend and the real needs.

    0 讨论(0)
  • 2020-11-28 04:20

    Another reason to not use default_scope is when you're deleting an instance of a model that has a 1 to many relation with the default_scope model

    Consider for example:

        class User < ActiveRecord::Base
          has_many :posts, dependent: :destroy
        end 
    
        class Post < ActiveRecord::Base
          default_scope { where(published: true) }
          belongs_to :user
        end
    

    Calling user.destroy will delete all the posts that are published, but it won't delete posts that are unpublished. Hence the database will throw a foreign key violation because it contains records that reference the user you want to remove.

    0 讨论(0)
  • 2020-11-28 04:24

    Problem 1

    Lets consider the basic example:

    class Post < ActiveRecord::Base
      default_scope { where(published: true) }
    end
    

    The motivation to make the default published: true, might be to make sure you have to be explict when wanting to show unpublished (private) posts. So far so good.

    2.1.1 :001 > Post.all
      Post Load (0.2ms)  SELECT "posts".* FROM "posts"  WHERE "posts"."published" = 't'
    

    Well this is pretty much what we expect. Now lets try:

    2.1.1 :004 > Post.new
     => #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
    

    And there we have the first big problem with default scope:

    => default_scope will affect your model initialization

    In a newly created instance of such a model, the default_scope will be reflected. So while you might have wanted to be sure to not list unpublished posts by chance, you're now creating published ones by default.

    Problem 2

    Consider a more elaborate example:

    class Post < ActiveRecord::Base
      default_scope { where(published: true) }
      belongs_to :user
    end 
    
    class User < ActiveRecord::Base
      has_many :posts
    end
    

    Lets get the first users posts:

    2.1.1 :001 > User.first.posts
      Post Load (0.3ms)  SELECT "posts".* FROM "posts"  WHERE "posts"."published" = 't' AND "posts"."user_id" = ?  [["user_id", 1]]
    

    This looks like expected (make sure to scroll all the way to the right to see the part about the user_id).

    Now we want to get the list of all posts - unpublished included - say for the logged in user's view. You'll realise you have to 'overwrite' or 'undo' the effect of default_scope. After a quick google, you'll likely find out about unscoped. See what happens next:

    2.1.1 :002 > User.first.posts.unscoped
      Post Load (0.2ms)  SELECT "posts".* FROM "posts"
    

    => Unscoped removes ALL scopes that might normally apply to your select, including (but not limited to) associations.

    There are multiple ways to overwrite the different effects of the default_scope. Getting that right gets complicated very quickly and I would argue not using the default_scope in the first place, would be a safer choice.

    0 讨论(0)
  • 2020-11-28 04:32

    default_scope is often recommended against because it is sometimes incorrectly used to limit the result set. A good use of default_scope is to order the result set.

    I would stay away from using where in default_scope and rather create a scope for that.

    0 讨论(0)
  • 2020-11-28 04:33

    I only find default_scope to be useful only in ordering some parameters to be in asc or desc order in all situation. Otherwise I avoid it like plague

    0 讨论(0)
提交回复
热议问题