通过协会属于

考虑到以下关联,我需要参考 QuestionChoice是通过 Choice模型连接的。我一直试图使用 belongs_to :question, through: :answer来执行这个操作。

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

但是我想使用它,因为我想能够做 validates_uniqueness_of

我可能忽略了一些简单的事情。任何帮助都会很感激。

127633 次浏览

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

有关 has_many魔术的信息,请参阅 ActiveRecord: : 协会文档。

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

如果您有妄想症,可以向 Choice添加一个自定义验证,以确认答案的 question_id匹配,但似乎最终用户永远不应该有机会提交会造成这种不匹配的数据。

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

这就是你想要的吗?

我会按照这样的思路建立一个模型:

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

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

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 从数据库加载 answer,然后从数据库加载 question。这可以在以后通过快速加载所需的关联(即 c = Choice.first(include: {answer: :question}))进行优化,然而,如果这种优化是必要的,那么 stephencelis 的答案可能是一个更好的性能决策。

对于某些选择,有一个时间和地点,我认为这个选择在原型开发时更好。除非我知道它用于不常见的用例,否则我不会将它用于生产代码。

你也可以委派:

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

只要在你的 :through中使用 has_one而不是 belongs_to,像这样:

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

与此无关,但是我不愿意在数据库中使用 validates _ 惟一性 _ of,而是使用适当的惟一约束。当您在 ruby 中执行此操作时,就有了比赛条件。

所以你不能有你想要的行为,但你可以做一些感觉像它。你想能够做 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

这样你就可以在 选择上提问了