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

luc*_*xum 0 model ruby-on-rails

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

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

我的问题是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
Run Code Online (Sandbox Code Playgroud)

我的代码段模型:

class Snippet < ActiveRecord::Base
  has_many :comments
  has_many :likes
  belongs_to :user
end
Run Code Online (Sandbox Code Playgroud)

我的评论模型:

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :snippet
  has_many :likes
end
Run Code Online (Sandbox Code Playgroud)

我喜欢的模特:

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
Run Code Online (Sandbox Code Playgroud)

我不能同时引用它们,我觉得创建一种新类型的Like对于应用程序中的每种内容都会很混乱.

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

Bar*_*cha 5

您正在寻找的是一个多态协会,可以通过Rails和活动记录轻松完成.

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

def change
  create_table :likes do |t|
    # other columns ...
    t.references :likeable, polymorphic: true
    t.timestamps
  end
end
Run Code Online (Sandbox Code Playgroud)

这一切都为建立一个likeable_idlikeable_type它将会引用一个特定列id和类type(在你的情况下,type将可能是"评论"或"片段").在此之后,您可以设置这样的关联

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
Run Code Online (Sandbox Code Playgroud)