2011-07-02 9 views
40

私がやろうとしていること:Rails Associations - has_many =>:through - しかし同じモデル

私はブログを持っており、メインポストの下に関連記事を表示したいと考えています。

class Post < ActiveRecord::Base 

    has_many :related_posts 
    has_many :posts, :through => :related_posts 

end 

そして参加モデル/テーブル内の

class RelatedPost < ActiveRecord::Base 

    belongs_to :post 

end 

そしてもちろん、テーブルがあるが2つのpost_id列を持つrelated_postsと呼ばれます。

は明らかにこれにはいくつかの欠陥があり、私はRailsの中に、この関連の仕事をするかどうかはわかりません。

答えて

53

を取ることをお勧めします。

私はあなたのユースケースのために働くアプリケーションを作成しました。 post.inverse_related_postsはあなたを投稿する関連するすべてのポストを与える一方で

post.related_postsは、あなたのポストから関連するすべてのポストを与えるだろう。

class Post < ActiveRecord::Base 
    has_many :related_posts_association, :class_name => "RelatedPost" 
    has_many :related_posts, :through => :related_posts_association, :source => :related_post 
    has_many :inverse_related_posts_association, :class_name => "RelatedPost", :foreign_key => "related_post_id" 
    has_many :inverse_related_posts, :through => :inverse_related_posts_association, :source => :post 
end 

class RelatedPost < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :related_post, :class_name => "Post" 
end 

マイスキーマ:ここ

は私のモデルがどのように見えるかだ

ActiveRecord::Schema.define(:version => 20110702194300) do 

    create_table "posts", :force => true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "related_posts", :force => true do |t| 
    t.integer "post_id" 
    t.integer "related_post_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

end 

は、ここでの関係を実証することをコンソールセッションのダンプです。上記以降

ruby-1.9.2-p180:001:0>> p = Post.create! name: "Hello" 
    SQL (23.5ms) INSERT INTO "posts" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Sat, 02 Jul 2011 20:03:43 UTC +00:00], ["name", "Hello"], ["updated_at", Sat, 02 Jul 2011 20:03:43 UTC +00:00]] 
# => #<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43"> 
ruby-1.9.2-p180:002:0>> p2 = Post.create! name: "World" 
    SQL (1.0ms) INSERT INTO "posts" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Sat, 02 Jul 2011 20:03:48 UTC +00:00], ["name", "World"], ["updated_at", Sat, 02 Jul 2011 20:03:48 UTC +00:00]] 
# => #<Post id: 2, name: "World", created_at: "2011-07-02 20:03:48", updated_at: "2011-07-02 20:03:48"> 
ruby-1.9.2-p180:003:0>> p.related_posts 
    Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."related_post_id" WHERE "related_posts"."post_id" = 1 
# => [] 
ruby-1.9.2-p180:004:0>> p2.related_posts 
    Post Load (0.4ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."related_post_id" WHERE "related_posts"."post_id" = 2 
# => [] 
ruby-1.9.2-p180:005:0>> p.related_posts << p2 
    SQL (0.7ms) INSERT INTO "related_posts" ("created_at", "post_id", "related_post_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Sat, 02 Jul 2011 20:04:01 UTC +00:00], ["post_id", 1], ["related_post_id", 2], ["updated_at", Sat, 02 Jul 2011 20:04:01 UTC +00:00]] 
# => [#<Post id: 2, name: "World", created_at: "2011-07-02 20:03:48", updated_at: "2011-07-02 20:03:48">] 
ruby-1.9.2-p180:006:0>> RelatedPost.all 
    RelatedPost Load (0.4ms) SELECT "related_posts".* FROM "related_posts" 
# => [#<RelatedPost id: 1, post_id: 1, related_post_id: 2, created_at: "2011-07-02 20:04:01", updated_at: "2011-07-02 20:04:01">] 
ruby-1.9.2-p180:007:0>> p2.inverse_related_posts 
    Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."post_id" WHERE "related_posts"."related_post_id" = 2 
# => [#<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43">] 
ruby-1.9.2-p180:008:0>> p = Post.first 
    Post Load (0.5ms) SELECT "posts".* FROM "posts" LIMIT 1 
# => #<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43"> 
ruby-1.9.2-p180:009:0>> p2.related_posts << p 
    SQL (25.7ms) INSERT INTO "related_posts" ("created_at", "post_id", "related_post_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Sat, 02 Jul 2011 20:05:29 UTC +00:00], ["post_id", 2], ["related_post_id", 1], ["updated_at", Sat, 02 Jul 2011 20:05:29 UTC +00:00]] 
    Post Load (0.3ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."related_post_id" WHERE "related_posts"."post_id" = 2 
# => [#<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43">] 
ruby-1.9.2-p180:010:0>> p2.related_posts 
# => [#<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43">] 
ruby-1.9.2-p180:011:0>> exit 


Loading development environment (Rails 3.1.0.rc4) 
ruby-1.9.2-p180:001:0>> Post.first.related_posts 
    Post Load (0.3ms) SELECT "posts".* FROM "posts" LIMIT 1 
    Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."related_post_id" WHERE "related_posts"."post_id" = 1 
# => [#<Post id: 2, name: "World", created_at: "2011-07-02 20:03:48", updated_at: "2011-07-02 20:03:48">] 
ruby-1.9.2-p180:002:0>> Post.last.related_posts 
    Post Load (0.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1 
    Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "related_posts" ON "posts"."id" = "related_posts"."related_post_id" WHERE "related_posts"."post_id" = 2 
# => [#<Post id: 1, name: "Hello", created_at: "2011-07-02 20:03:43", updated_at: "2011-07-02 20:03:43">] 
+3

。ありがとう。 – s84

+0

複数形を使う方がより適切だと思います。 'has_many:related_posts_association ** s **、:class_name =>" RelatedPost "' –

+0

@Filipposあなたの解決策は何ですか? – Nobita

11

あなたは自己参照関連を探しています。

私はあなたが興味深い質問だったインスピレーションhere.