belongs_to通过协会

vin*_*boy 133 activerecord ruby-on-rails ruby-on-rails-3

鉴于以下关联,我需要引用从模型中附加的Questiona .我一直在尝试使用它来执行此操作.ChoiceChoicebelongs_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
Run Code Online (Sandbox Code Playgroud)

我正进入(状态

NameError未初始化的常量 User::Choice

当我尝试做的时候 current_user.choices

它工作正常,如果我不包括

belongs_to :question, :through => :answer
Run Code Online (Sandbox Code Playgroud)

但我想用它,因为我希望能够做到这一点 validates_uniqueness_of

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

Ren*_*nra 356

你也可以委派:

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

  • +1,这是最干净的方法.(至少我能想到) (23认同)
  • 有没有办法用JOIN做到这一点,以便它不使用这么多的查询? (9认同)
  • +1,http://www.simonecarletti.com/blog/2009/12/inside-ruby-on-rails-delegate/ (5认同)
  • @Tallboy对主键的一些完美索引的选择查询几乎总是比任何单个JOIN查询更好.联接使数据库努力工作. (2认同)
  • @affinities23:这取决于您的特定要求。您可能想要没有任何公司的“易变”员工。然而,这里的 allow_nil 意味着如果 ```dog.employee``` 为 nil,那么对 ```dog.company``` 的调用不会失败,只会返回 nil。即使你总是希望这些东西是必需的,有这个也很好,因为你总是可以去 Rails 控制台并输入 ```dog = Dog.new```。那时你有一个非存在的记录,你仍然可以做```dog.company``` 没有任何失败。 (2认同)

mrm*_*mrm 105

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

class Choice
  belongs_to :user
  belongs_to :answer
  has_one :question, :through => :answer
end
Run Code Online (Sandbox Code Playgroud)

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

  • 这个解决方案的大警告.每当你保存选择时,它将始终保存问题,除非设置了"autosave:false". (34认同)

ste*_*lis 58

一个belongs_to协会不能有:through选择.你最好缓存question_idon Choice并为表添加一个唯一索引(特别是因为validates_uniqueness_of它容易出现竞争条件).

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

  • &gt;&gt; 听起来像最终用户永远不应该有机会提交会造成这种不匹配的数据。-- 您永远无法保证用户“没有机会做某事”,除非您对此进行明确的服务器端检查。 (2认同)