Domanda

Sto creando un piccolo servizio di microblogging in stile Twitter in cui gli utenti possono seguire altri utenti e ricevere un feed dei loro messaggi

Ho i seguenti modelli:

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

Per ottenere un feed per l'utente corrente, voglio eseguire la seguente query SQL:

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;

Qual è il modo ActiveRecord corretto per farlo?

È stato utile?

Soluzione

Non sono sicuro di quello che stai cercando, ma ecco il mio suggerimento:

Presumo che tu abbia altri scopi per quella classe Follow, altrimenti non ne vedo lo scopo.

Il modo "corretto" " (cioè il mio modo completamente soggettivo) di farlo sarebbe effettivamente qualcosa del genere:

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

Quindi creare la seguente tabella:

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

E sei pronto:

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

followed.followers << follower

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

Ma da quello che lo faccio, vuoi mostrare tutti i messaggi di tutti i follower allo stesso tempo.

Ciò dovrebbe essere possibile aggiungendo

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

alla classe Utente , ma non so quanto sarebbe corretto in questo modo. O potrebbe essere possibile ottenere con estensioni di associazione, ma lì non posso davvero dare alcun esempio.

Aggiornamento: Modificando: class_name, lo assocerà al Message.id , non ci ho pensato, quindi non sarà corretto in questo modo.

Quindi l'unico "simpatico" l'opzione è di passare attraverso la classe User come nel primo esempio. Le uniche altre opzioni che posso vedere sono le estensioni di associazione (di cui non posso darti un esempio) o forse usando un'istruzione 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})'

Probabilmente devi personalizzare quell'istruzione sql per far funzionare tutto, ma almeno dovresti ottenere l'immagine :)

Altri suggerimenti

La disposizione di Keijro funzionerebbe meglio, anche se se hai bisogno della tabella Follow, puoi eseguire la query SQL che hai specificato come segue:

Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"} )
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top