Problema 1
Consideremos el ejemplo básico:
class Post < ActiveRecord::Base
default_scope { where(published: true) }
end
La motivación para establecer el valor predeterminado published: truepodría ser asegurarse de tener que ser explícito cuando desee mostrar publicaciones no publicadas (privadas). 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, default_scopese reflejará. Entonces, si bien es posible que haya querido asegurarse de no enumerar publicaciones no publicadas por casualidad, ahora está creando las publicadas de forma predeterminada.
Problema 2
Considere 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 los 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 se esperaba (asegúrese de desplazarse completamente hacia la derecha para ver la parte sobre user_id).
Ahora queremos obtener la lista de todas las publicaciones, incluidas las no publicadas, 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 rápido google, es probable que lo descubras unscoped. Mira lo que pasa después:
2.1.1 :002 > User.first.posts.unscoped
Post Load (0.2ms) SELECT "posts".* FROM "posts"
=> Sin ámbito elimina TODOS los ámbitos que normalmente podrían aplicarse a su selección, incluidas (entre otras) las asociaciones.
Hay varias formas de sobrescribir los diferentes efectos de default_scope. Hacer eso bien se complica muy rápidamente y argumentaría que no usar el default_scopeen primer lugar, sería una opción más segura.
unscopedlugar deldefault_scopeproblema n. ° 2default_scopees cuando se quiere algo que debe clasificarse:default_scope { order(:name) }.Otra razón para no usar
default_scopees cuando está eliminando una instancia de un modelo que tiene una relación de 1 a muchos con eldefault_scopemodeloConsidere por ejemplo:
Las llamadas
user.destroyeliminarán todas las publicaciones que sonpublished, pero no eliminarán las publicaciones que sí lo seanunpublished. Por lo tanto, la base de datos arrojará una violación de clave foránea porque contiene registros que hacen referencia al usuario que desea eliminar.fuente
default_scope a menudo se recomienda contra 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 del uso
whereen default_scope y más bien crearía un alcance para eso.fuente
default_scopeúnico contieneorder. Este comportamiento deunscopedes bastante inesperado.Para mí no es una mala idea, ¡ pero debe usarse con precaución! Hay un caso en el que siempre quise ocultar ciertos registros cuando se establece un campo.
default_scopedebe coincidir con el valor predeterminado DB (por ejemplo:{ where(hidden_id: nil) })unscopedmétodo que evitará sudefault_scopeEntonces dependerá y las necesidades reales.
fuente
Sólo encuentro
default_scopepara ser útil sólo en ordenar algunos parámetros para estar enascodescorden en toda situación. De lo contrario lo evito como pestefuente