在rails模型中选择两个可能的关联之一

时间:2014-11-02 17:38:49

标签: ruby-on-rails model

新手到这里的铁路。我正在创建一个应用来管理用户,文本片段,片段评论和喜欢。

每个用户都有很多代码段并且有很多评论。 每个片段属于某个用户,有很多评论,并且可以有很多喜欢。 每个评论都属于某个用户,属于一个片段,可以有很多喜欢。

我的问题在于Like模型。 A like属于某个用户,属于EITHER片段或注释。

我的迁移看起来像这样:

class CreateLikes < ActiveRecord::Migration
  def change
    create_table :likes do |t|
      t.references :user
      t.references :snippet # or :comment...?

      t.timestamps
    end
  end
end

我的代码段模型:

class Snippet < ActiveRecord::Base
  has_many :comments
  has_many :likes
  belongs_to :user
end

我的评论模型:

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :snippet
  has_many :likes
end

我喜欢的模特:

class Like < ActiveRecord::Base
  belongs_to: :user
  # belongs to either :snippet or :comment, depending on
  # where the like is, and what controller it was submitted to
end

我无法引用这两种内容,我觉得要为应用中的各种内容创建一种新类型的内容会很混乱。

如何决定是在引用代码段还是引用每条代码的注释之间进行选择?

2 个答案:

答案 0 :(得分:5)

您正在寻找的内容称为Polymorphic Association,可以通过Rails和活动记录轻松完成。

您需要稍微修改您的Like迁移,以包含其他_type列。最简单的方法是迁移。

def change
  create_table :likes do |t|
    # other columns ...
    t.references :likeable, polymorphic: true
    t.timestamps
  end
end

所有这一切都是创建一个likeable_id和一个likeable_type列,它将引用特定的id和类type(在您的情况下,type将是&#34;评论&#34;或&#34; Snippet&#34;)。在此之后,您可以设置这样的关联

class Like < ActiveRecord::Base
  belongs_to :likeable, polymorphic: true
end

class Snippet < ActiveRecord::Base
  has_many :likes, as: :likeable
end

class Comment < ActiveRecord::Base
  has_many :likes, as: :likeable
end

答案 1 :(得分:1)

你需要看看Rails中的多态关联。 RailsCasts有一个很好的插曲,即http://railscasts.com/episodes/154-polymorphic-association

在这里,我将为创建一个多态模型,并使评论片段 可爱

class CreateLikes < ActiveRecord::Migration
  def change
    create_table :likes do |t|
      t.integer :likeable_id
      t.string :likeable_type
      t.references :user
      t.timestamps
    end
  end
end
class Snippet < ActiveRecord::Base
  has_many :comments
  has_many :likes, as: :likeable
  belongs_to :user
end
class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :snippet
  has_many :likes, as: :likeable
end

class Like < ActiveRecord::Base
  belongs_to: :user
  belongs_to :likeable, :polymorphic => true
  # belongs to either :snippet or :comment, depending on
  # where the like is, and what controller it was submitted to
end