has_many通过自我参照联想

时间:2009-10-20 14:15:40

标签: ruby-on-rails associations has-many-through self-reference

我想(作为示例)为一个人的朋友创建一个has_many关联给所有帖子,类似于has_many :remote_posts给我一些person > friends > person > posts

..这就是我要怎么做的

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

现在,

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

......我收到了这个错误..

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

除了外键错误 - 似乎友谊协会根本没有发挥作用。我认为这可能是因为:source => :posts,因为posts关联会进入两次。

我可以写一些finder sql(这就是我现在正在工作的东西),虽然我很快就会这样做。

有关如何使其发挥作用的任何想法?

2 个答案:

答案 0 :(得分:1)

这个怎么样:

FriendShip课程中,添加:

has_many :posts, :through => :person


并在Person类中,将remote_posts更改为:

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

答案 1 :(得分:0)

嵌套has_many :through关系怎么样?这似乎对我有用:

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

注意:这需要此nested_has_many_through plugin。 (注意:直接链接到github repos似乎被打破了......但是尽管出现了错误信息,那个回购仍然存在。)