2

Je veux (par exemple) créer une association has_many à tous les messages par des amis d'une personne, quelque chose comme has_many :remote_posts pour me donner quelque chose comme person > friends > person > posts.has_many par l'intermédiaire de l'association auto référentielle

..here est de savoir comment j'aller à ce sujet

script/generate model post title:string person_id:integer 
script/generate model friendship person_id:integer friend_id:integer 
script/generate model person name:string 

class Person < ActiveRecord::Base 
    has_many :posts 
    has_many :friendships, :foreign_key => 'friend_id' 
    has_many :people, :through => :friendships 
    has_many :remote_posts, :class_name => 'Post', :through => :people, :source => :posts 
end 
class Friendship < ActiveRecord::Base 
    belongs_to :person 
    #also has a 'friend_id' to see who the friendship is aimed at 
end 
class Post < ActiveRecord::Base 
    belongs_to :person 
end 

# generate some people and friends 
{'frank' => ['bob','phil'], 'bob' => ['phil']}.each {|k,v| 
    v.each {|f| 
    Friendship.create(
     :person_id => Person.find_or_create_by_name(f).id, 
     :friend_id => Person.find_or_create_by_name(k).id 
    ) 
    } 
} 
# generate some posts 
Person.all.each {|p| 
    p.posts.create({:title => "Post by #{p.name}"}) 
} 

Maintenant,

Person.first.friendships # ..works 
Person.first.people # (friends) ..works 
Person.first.posts # ..works 
Person.first.remote_posts #.... 

... et je reçois cette erreur ..

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: people.person_id: SELECT "posts".* FROM "posts" INNER JOIN "people" ON "posts".person_id = "people".id WHERE (("people".person_id = 1))

En dehors de l'erreur de clé étrangère - semble comme l'association des amitiés ne vient pas en jeu du tout. Je pensais que cela pourrait être à cause du :source => :posts, puisque l'association posts viendrait en elle deux fois.

Je pourrais écrire un finder sql (et c'est ce que j'ai en ce moment), mais je ferais mieux de le faire de cette façon.

Des idées pour que cela fonctionne?

Répondre

1

Que diriez-vous ceci:

Dans la classe FriendShip, ajoutez:

has_many :posts, :through => :person 


et dans la classe Person, modifiez les remote_posts à:

has_many :remote_posts, :class_name => 'Post', 
     :through => :friendships, :source => :person 
+0

JRL, C'est bien mieux! Malheureusement, il ne fonctionne toujours pas complètement (peut-être en raison d'un problème non lié) lorsque vous appelez. Person.find_by_name (« franche ») remote_posts feux ..Il hors ce SQL: SELECT « messages » . * FROM "posts" INNER JOIN "amitiés" ON "posts" .id = "amitiés" .person_id OERE (("amitiés" .friend_id = 2)) Il aurait dû rejoindre sur posts.person_id au lieu de posts.id (donc il retourne les messages avec le même ID que vos amis) J'ai essayé de mettre dans certains: foreign_key, mais ne semble pas fonctionner. Merci pour votre réponse! –

+0

Damnit - J'aurais dû savoir qu'il ne formaterait pas correctement ... Le problème est que la personne # remote_posts utilise post.id au lieu de post.person_id - mais je pense que c'est 80% là! –

0

Que diriez-vous imbriqué has_many :through relation. Cela semble fonctionner pour moi:

class Friendship < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :friend, :class_name => 'Person' 
    has_many :posts, :through => :friend, :source => :posts 
end 
class Person < ActiveRecord::Base 
    has_many :posts 
    has_many :friendships, :foreign_key => 'friend_id' 
    has_many :people, :through => :friendships 
    has_many :remote_posts, :through => :friendships, :source => :posts 
end 

Note: cela nécessite cette nested_has_many_through plugin. (Note: le lien direct vers les repos de github semble être cassé ... mais ce repo est là malgré le message d'erreur.)