update rails query left joins includes has_and_belongs_to_many ruby-on-rails activerecord

query - Ruby on Rails tiene_muchos a través de relaciones autorreferenciales siguientes/seguidores



rails sql query (2)

Hay una cantidad de publicaciones e hilos en has_many: through, pero no he encontrado ninguno que cubra específicamente lo que estoy tratando de hacer.

Tengo un modelo de Usuario y un modelo de Amistades. Un usuario tiene muchos usuarios que los siguen, así como muchos seguidores. Es el modelo habitual de Twitter.

Para un usuario dado, quiero configurar relaciones de Active Record que devuelvan los usuarios reales que siguen al usuario y que el usuario es seguidor de.

Estas son las relaciones que he configurado:

class User < ActiveRecord::Base has_many :following, :class_name => ''User'', :through => :friendships, :foreign_key => ''user_id'' has_many :followers, :class_name => ''User'', :through => :friendships, :foreign_key => ''friend_id'' end class Friendship < ActiveRecord::Base belongs_to :user belongs_to :following, :class_name => ''User'', :foreign_key => ''friend_id'' belongs_to :follower, :class_name => ''User'', :foreign_key => ''user_id'' end

La siguiente relación funciona: genera la unión siguiente:

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.friend_id WHERE ((`friendships`.user_id = 1))

Todo es grandioso

Sin embargo, la relación de seguidor no funciona. Intenté varias variaciones, pero la mayoría parece devolver el mismo conjunto de resultados que Siguientes.

Necesito que la unión se configure de la siguiente manera para devolver el conjunto de resultados correcto.

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = 1));

¿Dónde estoy equivocado?

Puedo configurar esto usando la opción finder_sql en has_many, pero parece que debería haber una mejor manera.

has_many :followers, :class_name => ''User'', :finder_sql => ''SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = #{ id }))''

¡Gracias!

Hice un poco de progreso y, finalmente, conseguí que la relación funcionara al dividir las relaciones en dos partes, como se muestra en esta respuesta: autorreferencial has_many: a través de personalizado: cuestión de clave principal

# FOLLOWING has_many :friendships_to, :foreign_key => ''user_id'', :class_name => ''Friendship'' has_many :following, :through => :friendships_to, :class_name => ''User'' # FOLLOWERS has_many :friendships_from, :foreign_key => ''friend_id'', :class_name => ''Friendship'' has_many :followers, :through => :friendships_from, :class_name => ''User''

Sin embargo, aunque era posible tener una versión de una línea de la relación para seguir

has_many :following, :class_name => ''User'', :through => :friendships, :foreign_key => ''user_id''

Todavía no pude hacer que funcione para los seguidores. ¿Todavía te preguntas cómo se podría hacer esto?


Debe asegurarse de que ActiveRecord sepa cuál es la asociación de origen para los # amigos del usuario y también los seguidores y especifique la clase y la clave foreign_key para las relaciones que ActiveRecord no puede extrapolar de los nombres de las asociaciones.

class Following < ActiveRecord::Base belongs_to :user belongs_to :followed, :class_name => ''User'' end class User < ActiveRecord::Base has_many :followings has_many :friends, :through => :followings, :source => ''followed'' has_many :followeds, :class_name => ''Following'', :foreign_key => ''followed_id'' has_many :followers, :through => :followeds, :source => :user end


Soy un novato en un proceso de aprendizaje, pero estos modelos me parecen más limpios:

class User < ActiveRecord::Base has_many :followings has_many :followers, through: :followings end class Following < ActiveRecord::Base belongs_to :user belongs_to :follower, class_name: ''User'' end