测验模型的未定义方法

时间:2016-06-21 00:20:06

标签: ruby-on-rails

调查有很多问题,有很多答案:

class Survey < ActiveRecord::Base
    has_many :questions, :dependent => :destroy
    accepts_nested_attributes_for :questions, :reject_if => -> (a) {a[:content].blank? }, :allow_destroy => true
end

class Question < ActiveRecord::Base
    belongs_to :survey
    has_many :answers, :dependent => :destroy
    accepts_nested_attributes_for :answers, :reject_if => -> (a) {a[:content].blank? }, :allow_destroy => true
end

class Answer < ActiveRecord::Base
    belongs_to :question
end

在SurveysController中,我这样做:

def show
    @survey = Survey.find(params[:id])
    @questions = @survey.questions
    @answers = @questions.answers
  end

我收到错误:

undefined method `answers' for #<Question::ActiveRecord_Associations_CollectionProxy:0x007f7f68af6948>

和rails指向此行作为问题:@answers = @questions.answers

为什么?

1 个答案:

答案 0 :(得分:1)

这是因为您尝试从所有问题中加载所有答案,但是您使用的语法旨在从单个问题中加载所有答案。

例如,这是正确的:

@question_1 = @survey.questions.first    # Notice the `first`
@answers = @question_1.answers           # Gets all answers for the `first` question

了解我如何获得单个question然后获得答案?这是对的。

现在,如果你想获得所有问题的所有答案,那么使用collect方法将会受益:

@questions = @survey.questions
@answers = @questions.collect(&:answers)

这个collect方法实质上是通过每个问题运行each循环并将其子集(answers)“收集”到数组中。

-

一种不太简洁,虽然更有效的方法是避免N + 1个查询并使用includes代替collect

@answers = []
@questions.includes(:answers).each do |q| 
    @answers << q.answers
end