2009-05-04 6 views
1

Ich baue eine kleine Mikrobloggingdienst Twitter Stil, in dem Benutzer andere Benutzer folgen können und einen Feed ihrer Nachrichtenmehrere schließt sich in Schienen mit Active

erhalten Ich habe die folgenden Modelle:

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 

zu erhalten eine Zuführung für den aktuellen Benutzer, möchte ich die folgende SQL-Abfrage auszuführen:

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; 

Was ist der richtige Weg Active dies zu tun?

Antwort

1

nicht sicher, was Sie suchen, aber hier ist mein Vorschlag:

Ich gehe davon aus, dass Sie für diese Folgen Klasse andere Zwecke, sonst sehe ich nicht den Zweck davon.

Die „richtige Weg“ (dh meine ganz subjektive Art und Weise) es tatsächlich so etwas wie dies zu tun wäre:

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 

erstellen Sie die folgende Tabelle:

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

Und du bist set:

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

followed.followers << follower 

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

Aber von dem, was ich es machen, wollen Sie alle Nachrichten aus allen Anhängern zeigen, gleichzeitig.

Dies sollte möglich sein, zu erreichen

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

zur Benutzer Klasse hinzufügen, aber ich weiß nicht, wie richtig auf diese Weise sein würde. Oder es könnte mit Assoziationserweiterungen möglich sein, aber ich kann hier keine Beispiele nennen.

Update: den Durch Änderung: class_name, wird es mit den Message.id assoziieren, nicht darüber dachte, so dass es auf diese Weise nicht korrekt.

Also ist die einzige "nette" Option, die Benutzerklasse wie im ersten Beispiel zu durchlaufen. Die einzigen anderen Optionen, die ich sehen kann, sind entweder die Assoziationserweiterungen (denen ich kein Beispiel geben kann) oder vielleicht eine Finder-Anweisung.

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})' 

Sie haben wahrscheinlich zu, dass die SQL-Anweisung anpassen, alles zu bekommen, zu arbeiten, aber zumindest sollten Sie das Bild bekommen :)

+0

has_and_belongs_to_many: followed_messages,: foreign_key => 'follower_id': class_name => 'Nachricht',: association_foreign_key => 'followed_id' erzeugt Sie können die SQL-Abfrage, die Sie wie folgt angegeben ausführen die SQL: SELECT * FROM Nachrichten INNER JOIN folgt ON messages.id = folgt.followee_id WHERE (follows.follower_id = ) aber ich brauche es sein messages.user_id = follows.followee_id Gibt es eine Möglichkeit, das zu tun? – Shalmanese

1

Keijro Arrangement besser funktionieren würde, aber wenn Sie die Follow-Tabelle benötigen, dann

Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"})