belongs_to通过协会

时间:2010-10-26 06:50:19

标签: ruby-on-rails ruby-on-rails-3 activerecord

鉴于以下关联,我需要引用从Question模型附加Choice的{​​{1}}。我一直在尝试使用Choice来执行此操作。

belongs_to :question, through: :answer

我正在

  

NameError未初始化的常量class User has_many :questions has_many :choices end class Question belongs_to :user has_many :answers has_one :choice, :through => :answer end class Answer belongs_to :question end class Choice belongs_to :user belongs_to :answer belongs_to :question, :through => :answer validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ] end

当我尝试User::Choice

如果我不包含

,它可以正常工作
current_user.choices

但我想使用它,因为我希望能够执行belongs_to :question, :through => :answer

我可能忽略了一些简单的事情。任何帮助将不胜感激。

7 个答案:

答案 0 :(得分:339)

您也可以委派:

class Company < ActiveRecord::Base
  has_many :employees
  has_many :dogs, :through => :employees
end

class Employee < ActiveRescord::Base
  belongs_to :company
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :employee

  delegate :company, :to => :employee, :allow_nil => true
end

答案 1 :(得分:94)

只需在has_one中使用belongs_to代替:though,就像这样:

class Choice
  belongs_to :user
  belongs_to :answer
  has_one :question, :through => :answer
end

不相关,但我会犹豫是否使用validates_uniqueness_of而不是在数据库中使用适当的唯一约束。当您在红宝石中执行此操作时,您会遇到竞争条件。

答案 2 :(得分:57)

belongs_to关联不能有:through选项。您最好在question_id上缓存Choice并为表添加唯一索引(特别是因为validates_uniqueness_of容易出现竞争条件)。

如果你是偏执狂,请向Choice添加一个自定义验证,确认答案的question_id匹配,但听起来最终用户永远不应该有机会提交会创建的数据这种不匹配。

答案 3 :(得分:4)

我的方法是创建一个虚拟属性,而不是添加数据库列。

class Choice
  belongs_to :user
  belongs_to :answer

  # ------- Helpers -------
  def question
    answer.question
  end

  # extra sugar
  def question_id
    answer.question_id
  end
end

这种方法非常简单,但需要权衡。它要求Rails从db加载answer,然后question。这可以通过急切加载您需要的关联(即c = Choice.first(include: {answer: :question}))进行优化,但是,如果需要进行此优化,那么stephencelis的回答可能是更好的性能决策。

某些选择有时间和地点,我认为在原型设计时这种选择会更好。我不会将它用于生产代码,除非我知道它是用于不经常的用例。

答案 4 :(得分:1)

听起来你想要的是一个有很多问题的用户 该问题有很多答案,其中一个是用户选择。

这就是你追求的吗?

我会按照以下方式对此进行建模:

class User
  has_many :questions
end

class Question
  belongs_to :user
  has_many   :answers
  has_one    :choice, :class_name => "Answer"

  validates_inclusion_of :choice, :in => lambda { answers }
end

class Answer
  belongs_to :question
end

答案 5 :(得分:1)

所以你不能拥有你想要的行为,但你可以做一些感觉就像它的事情。您希望能够Choice.first.question

我过去所做的就是这样的事情

class Choice
  belongs_to :user
  belongs_to :answer
  validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
  ...
  def question
    answer.question
  end
end

通过这种方式,您现在可以在选择

上调用问题

答案 6 :(得分:-1)

has_many :choices创建名为choices的关联,而不是choice。请尝试使用current_user.choices

有关has_many魔术的详细信息,请参阅ActiveRecord::Associations文档。