2010-03-05 13 views
2

Je travaille sur une application qui modélise les amitiés entre utilisateurs. Lorsque deux utilisateurs deviennent amis, deux instances de la classe d'amitié sont créées, une pour chaque direction de l'amitié. Cela est nécessaire car des autorisations différentes peuvent être définies dans chaque direction, ainsi que pour faciliter les recherches. Ainsi, nous recherchons toujours par user_id sans créer d'index supplémentaire et en doublant les recherches.Ruby on Rails: Est-il possible de: inclure l'autre jambe d'une table de joint circulaire?

Est-il possible, en utilisant soit find ou une portée nommée pour attirer un ami avec la contre-amitié? Je voudrais le faire parce que je permets aux utilisateurs d'éditer des permissions d'amitié qui sont stockées dans leur propre jambe de l'amitié, et ainsi quand j'indique l'information d'un ami à l'utilisateur je dois vérifier l'autre jambe pour voir comment les autorisations sont définies. (En aparté, cela vous semble-t-il une manière logique de faire les choses? Soit vous stockez dans le côté opposé, soit vous devez consulter le côté opposé avant l'affichage, les deux étant désagréables.)

concocter un lot de SQL qui fait le travail:

def self.secure_friends(user_id) 
    User.find_by_sql("SELECT u.*, cf.permissions 
        FROM users u 
        INNER JOIN friendships f ON u.id = f.friend_id 
        INNER JOIN friendships cf ON u.id = cf.user_id AND cf.friend_id = #{user_id} 
        WHERE ((f.user_id = #{user_id}) AND (f.status = #{Friendship::FULL}))") 
end 

la fonction retourne tous les noms d'amis et ids d'un utilisateur, ainsi que les autorisations. Cependant, cela ne semble pas idéal et signifie que je dois accéder aux permissions en appelant friend.permissions, où les permissions ne sont pas réellement un membre d'un ami mais sont juste fusionnées en tant qu'attribut par find_by_sql. Dans l'ensemble, je préfèrerais le faire avec un named_scope ou un appel find, mais malheureusement, chaque tentative que j'ai faite pour utiliser cette approche a entraîné des erreurs car Rails s'étouffe parce que la même table de jointure Friendship est jointe à la requête deux fois.

Répondre

2

Je ne suis pas sûr combien vous voulez faire, et combien vous permettez à un plug-in à faire - mais j'ai utilisé ce has_many_friends plugin avec succès: has_many_friends plugin at Github

Vous pouvez regarder la source et inspirez ... juste besoin d'un modèle d'amitié qui a des choses comme:

belongs_to :friendshipped_by_me, :foreign_key => "user_id", :class_name => "User" 
belongs_to :friendshipped_for_me, :foreign_key => "friend_id", :class_name => "User" 

, puis plus tard, dans votre classe d'utilisateurs ont:

has_many :friends_by_me, 
     :through => :friendships_by_me, 
     :source => :friendshipped_for_me 

Ou, juste

/app/modèles/utilisateur

has_many_friends 

plus tard:

@current_user.friends.each{|friend| friend.annoy!}