【问题标题】:Rails Associations - has_many => :through - but same modelRails Associations - has_many => :through - 但相同的模型
【发布时间】:2011-09-27 09:35:44
【问题描述】:

我想做什么:

我有一个博客,想在主帖下方显示相关帖子。

class Post < ActiveRecord::Base

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

end

然后在连接模型/表中

class RelatedPost < ActiveRecord::Base

  belongs_to :post

end

当然还有一个名为 related_posts 的表,其中包含两个 post_id 列。

显然这有几个缺陷,我只是不确定如何使这种关联在 Rails 中起作用。

【问题讨论】:

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


    【解决方案1】:

    这是一个有趣的问题。

    我刚刚为您的用例创建了一个工作应用程序。

    post.related_posts 将为您提供与 post 相关的所有帖子,而 post.inverse_related_posts 将为您提供与 post 相关的所有帖子。

    这是我的模型的样子:

    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">]
    

    【讨论】:

    • 我认为使用复数形式更合适。 has_many :related_posts_association**s**, :class_name =&gt; "RelatedPost"
    • @Filippos 你的解决方案是什么?
    【解决方案2】:

    您正在寻找自引用关联。

    我建议你获得灵感here.

    【讨论】:

    • 感谢您指向 RailsCasts。古老但令人惊叹的品质,仍然具有相关性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    相关资源
    最近更新 更多