ruby-on-rails - query - rails joins
¿Por qué el uso de los carriles default_scope a menudo recomienda no? (3)
Everywhere on Internet, las personas mencionan que usar los carriles default_scope
es una mala idea, y los mejores resultados para default_scope
en stackoverflow son sobre cómo sobrescribirlo. Esto se siente mal, y merece una pregunta explícita (creo).
Entonces, ¿por qué usar los rails default_scope
es una mala idea?
Problema 1
Consideremos el ejemplo básico:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
La motivación para publicar el valor predeterminado published: true
, podría ser asegurarse de que tiene que ser explicto cuando quiera mostrar publicaciones (privadas) no publicadas. Hasta aquí todo bien.
2.1.1 :001 > Post.all
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."published" = ''t''
Bueno, esto es más o menos lo que esperamos. Ahora intentemos:
2.1.1 :004 > Post.new
=> #<Post id: nil, title: nil, published: true, created_at: nil, updated_at: nil>
Y ahí tenemos el primer gran problema con el alcance predeterminado:
=> default_scope afectará la inicialización de su modelo
En una instancia recién creada de dicho modelo, se reflejará el default_scope
. Así que, aunque es posible que haya querido asegurarse de no incluir las publicaciones no publicadas por casualidad, ahora está creando las publicadas por defecto.
Problema 2
Considera un ejemplo más elaborado:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
Permite obtener las primeras publicaciones de usuarios:
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]]
Esto se ve como esperado (asegúrese de desplazarse completamente hacia la derecha para ver la parte sobre el ID_usuario).
Ahora queremos obtener la lista de todas las publicaciones, incluidas sin publicar, por ejemplo, para la vista del usuario conectado. Te darás cuenta de que tienes que ''sobrescribir'' o ''deshacer'' el efecto de default_scope
. Después de un Google rápido, es probable que descubras acerca de sin unscoped
. Vea lo que sucede a continuación:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Sin Cobertura elimina TODOS los ámbitos que normalmente se aplican a su selección, incluidas (entre otras) asociaciones.
Hay varias formas de sobrescribir los diferentes efectos del default_scope
. Hacerlo bien se complicated muy rápido y yo diría que no usar el default_scope
en primer lugar, sería una opción más segura.
Solo encuentro que default_scope
es útil solo para ordenar que algunos parámetros estén en orden asc
o desc
en todas las situaciones. De lo contrario, lo evito como la peste
default_scope se recomienda a menudo porque a veces se usa incorrectamente para limitar el conjunto de resultados. Un buen uso de default_scope es ordenar el conjunto de resultados.
Me mantendría alejado de usar where
en default_scope y más bien crearía un alcance para eso.