Question

Je construis un petit service de microblogging de style Twitter dans lequel les utilisateurs peuvent suivre d'autres utilisateurs et obtenir un flux de leurs messages

J'ai les modèles suivants:

class Follow < ActiveRecord::Base
  belongs_to :follower, :class_name => "User"
  belongs_to :followee, :class_name => "User"
end

class User < ActiveRecord::Base
  has_many :follows,   :foreign_key => 'follower_id',
                       :class_name => 'Follow'
  has_many :followers, :through => :follows
  has_many :followed,  :foreign_key => 'followee_id',
                       :class_name => 'Follow'
  has_many :followees, :through => :followed
  has_many :messages
end

class Message < ActiveRecord::Base
  belongs_to :user
end

Pour obtenir un flux pour l'utilisateur actuel, je souhaite exécuter la requête SQL suivante:

SELECT * FROM follows JOIN users JOIN messages WHERE follows.follower_id = current_user.id AND follows.followee_id = users.id AND users.id = messages.user_id;

Quelle est la bonne façon pour cela d’ActiveRecord?

Était-ce utile?

La solution

Je ne sais pas ce que vous cherchez, mais voici ma suggestion:

Je suppose que vous avez d'autres objectifs pour cette classe de suivi, sinon je ne vois pas le but.

La "manière correcte" (c’est-à-dire ma façon totalement subjective) de le faire serait en quelque sorte comme ceci:

class User < ActiveRecord::Base
  has_and_belongs_to_many :followers, :foreign_key => 'followed_id', 
      :class_name => 'User', :association_foreign_key => 'follower_id', 
      :include => [:messages]
  has_and_belongs_to_many :follows, :foreign_key => 'follower_id', 
      :class_name => 'User', :association_foreign_key => 'followed_id'
  has_many :messages
end

class Message < ActiveRecord::Base
  belongs_to :user
end

Créez ensuite le tableau suivant:

create_table :users_users, :id => false do |t|
  t.integer :followed_id
  t.integer :follower_id
end

Et vous êtes prêt:

followed = User.find :first
follower = User.find :last

followed.followers << follower

followed.followers.first.messages
followed.followers.first.followers.first.messages # etc...

Mais de ce que je fais, vous voulez afficher tous les messages de tous les abonnés en même temps.

Cela devrait être possible en ajoutant

 has_and_belongs_to_many :followed_messages, :foreign_key => 'follower_id', 
  :class_name => 'Message', :association_foreign_key => 'followed_id'

à la classe Utilisateur , mais je ne sais pas à quel point cela serait correct. Ou bien, il serait peut-être possible d’obtenir des extensions d’association, mais je ne peux pas vraiment donner d’exemples.

Mise à jour: En modifiant: nom_classe, il sera associé au Message.id , n'y a pas pensé, donc ce ne sera pas correct de cette façon.

Donc, le seul "sympa" L’option est de passer par la classe User comme dans le premier exemple. Les seules autres options que je peux voir sont les extensions d’association (pour lesquelles je ne peux pas vous donner d’exemple) ou peut-être une déclaration finder.

 has_many :followed_messages, :class_name => 'Message',
  :finder_sql => 'select * from messages where user_id in(select followed_id from users_users where follower_id = #{id})'

Vous devez probablement personnaliser cette instruction SQL pour que tout fonctionne, mais au moins vous devriez obtenir l'image :)

Autres conseils

L'arrangement de Keijro fonctionnerait mieux, mais si vous avez besoin de la table Follow, vous pouvez alors exécuter la requête SQL spécifiée comme suit:

Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"} )
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top