rails query inner includes example ruby-on-rails default-scope

ruby-on-rails - inner - rails query where



default_scope y asociaciones (5)

Supongamos que tengo un modelo de publicación y un modelo de comentario. Usando un patrón común, Publicar has_many Comentarios.

Si el comentario tiene un conjunto default_scope:

default_scope where("deleted_at IS NULL")

¿Cómo recupero fácilmente TODOS los comentarios en una publicación, independientemente del alcance? Esto produce resultados inválidos:

Post.first.comments.unscoped

Que genera las siguientes consultas:

SELECT * FROM posts LIMIT 1; SELECT * FROM comments;

En lugar de:

SELECT * FROM posts LIMIT 1; SELECT * FROM comments WHERE post_id = 1;

Corriendo:

Post.first.comments

Produce:

SELECT * FROM posts LIMIT 1; SELECT * FROM comments WHERE deleted_at IS NULL AND post_id = 1;

Entiendo el principio básico de la eliminación sin ámbito de todos los ámbitos existentes, pero ¿no debería ser consciente y mantener el alcance de la asociación?

¿Cuál es la mejor manera de sacar TODOS los comentarios?


De hecho, este es un problema muy frustrante que viola el principio de la menor sorpresa.

Por ahora, puedes escribir:

Comment.unscoped.where(post_id: Post.first)

Esta es la solución más elegante / simple de IMO.

O:

Post.first.comments.scoped.tap { |rel| rel.default_scoped = false }

La ventaja de este último:

class Comment < ActiveRecord::Base # ... def self.with_deleted scoped.tap { |rel| rel.default_scoped = false } end end

Entonces puedes hacer cosas divertidas:

Post.first.comments.with_deleted.order(''created_at DESC'')

Desde Rails 4, Model.all devuelve un ActiveRecord :: Relation, en lugar de una matriz de registros. Así que puedes (y deberías) usar all lugar del scoped :

Post.first.comments.all.tap { |rel| rel.default_scoped = false }


Por alguna extraña razón,

Comment.unscoped { Post.last.comments }

incluye el default_scope del Comment ,

sin embargo,

Comment.unscoped { Post.last.comments.to_a } Comment.unscoped { Post.last.comments.order }

No incluya el default_scope del Comment .

Experimenté esto en una sesión de rails console Rails 3.2.3 con Rails 3.2.3 .


Rails 4.1.1

Comment.unscope(where: :deleted_at) { Post.first.comments }

O

Comment.unscoped { Post.first.comments.scope }

Tenga en cuenta que agregué .scope , parece que este bloque debería devolver el tipo de ActiveRecord_AssociationRelation (lo que hace .scope ) no ActiveRecord_Associations_CollectionProxy (sin un .scope )


with_exlusive_scope está en desuso a partir de Rails 3. Ver este commit .

Antes (carriles 2):

Comment.with_exclusive_scope { Post.find(post_id).comments }

Después (Rieles 3):

Comment.unscoped { Post.find(post_id).comments }


class Comment def post_comments(post_id) with_exclusive_scope { find(all, :conditions => {:post_id => post_id}) } end end Comment.post_comments(Post.first.id)