Problema 1
Vamos considerar o exemplo básico:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
A motivação para fazer o padrão published: true
é garantir que você seja explícito quando desejar mostrar postagens (privadas) não publicadas. Por enquanto, tudo bem.
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't'
Bem, isso é praticamente o que esperamos. Agora vamos tentar:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
E aí temos o primeiro grande problema com o escopo padrão:
=> default_scope afetará a inicialização do modelo
Em uma instância recém-criada de um modelo desse tipo, default_scope
isso será refletido. Portanto, embora você queira ter certeza de não listar postagens não publicadas por acaso, agora você está criando postagens publicadas por padrão.
Problema 2
Considere um exemplo mais elaborado:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Permite obter as primeiras postagens de usuários:
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]]
Isso parece esperado (certifique-se de rolar todo o caminho para a direita para ver a parte sobre o user_id).
Agora queremos obter a lista de todas as postagens - inclusive não publicadas - para a visualização do usuário conectado. Você perceberá que precisa "substituir" ou "desfazer" o efeito de default_scope
. Depois de um rápido google, você provavelmente descobrirá unscoped
. Veja o que acontece a seguir:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Sem escopo remove TODOS os escopos que normalmente se aplicam ao seu select, incluindo (mas não limitado a) associações.
Existem várias maneiras de substituir os diferentes efeitos do default_scope
. Conseguir isso direito fica complicado muito rapidamente e eu diria que não usar o default_scope
em primeiro lugar, seria uma escolha mais segura.