我正在使用ActiveRecord开发rails项目。我正在做一些逐步的查询,似乎我缺少关键概念,因为我是Activerecord的新手。我无法在模型上获取id并因此执行查询。这是我的代码:
questions = JSON.parse(q)
selected_answers = questions.map do |ques|
ques['options'].map do |opt|
Answer.where(value: opt['title'])
end
end
participants = selected_answers.flatten!.map do |sa|
Participant.where(answers: sa.id)
end
stats[:answers] = participants.map do |p|
Answer.where(participants: p.id) #this line causes an error
end
我收到错误
NoMethodError (undefined method `id' for #<Participant::ActiveRecord_Relation:0x007fc478423bc0>):
app/services/survey_statistics.rb:143:in `block in get_question'
app/services/survey_statistics.rb:142:in `map'
app/services/survey_statistics.rb:142:in `get_question'
app/services/survey_statistics.rb:25:in `block in questions'
app/services/survey_statistics.rb:22:in `questions'
app/controllers/api/v1/reports_controller.rb:13:in `questions'
答案 0 :(得分:0)
看起来participants
是集合的集合。您正在使用map
,因此您的变量p
现在是一个集合(实际上Participant::ActiveRecord_Relation
告诉您它是一个集合),这就是它没有id
的原因。我会尝试再循环遍历集合(这次是p
),如下所示:
stats[:answers] = participants.map do |p|
p.map do |p1|
Answer.where(participants: p1.id)
end
end
您可以在此处找到相关问题:undefined method `id' for #<ActiveRecord::Relation []>
答案 1 :(得分:0)
它不起作用,因为你做了 map ,它构造了一个与 where 结合的数组,它还返回一个数组,所以你有数组数组:
stats[:answers] = participants.map do |p|
Answer.where(participants: p.id) #this line causes an error
end
您可以更简单地实现目标,据我所知,您可以使用此代码替换所有代码:
questions = JSON.parse(q)
titles = questions.each_with_object([]) do |q, a|
q["options"].each { |option| a << option["title"] }
end
participants_ids = Answer.where(value: titles).pluck(:participant_id)
stats[:answers] = Answer.where(participant_id: participant_ids)
答案 2 :(得分:0)
@ Pholochtairze的回答很明显。这个答案是删除所有这些调用地图并有效地获得所需的所有答案(双关语意图:p)
首先,您将获得所选答案的列表。我们要将所有标题保存到不同的变量中并使用它来获取所有答案。我们还将flat_map
用于最外层循环。
questions = JSON.parse(q)
titles = questions.flat_map do |ques|
ques['options'].map { |opt| opt['title'] }
end
selected_answers = Answer.where(value: titles)
flatten!
和其他!
方法的一个问题是,如果没有进行任何更改,它们会返回nil,因为您通常不想在链中使用它们。所以这里的重构是将调用移到map
方法中的where
。
participants = Participant.where(answers: selected_answers.map(&:id))
更好的重构是使用pluck
而不是map
,因为selected_answers
现在是ActiveRecord::Relation
对象。这将阻止Rails不必要地创建记录。
participants = Participant.where(answers: selected_answers.pluck(:id))
对于最后一部分,我们希望得到我们之前获得的参与者的答案。您仍然可以使用map
但我们再次使用pluck
来提高效率。
stats[:answers] = Answer.where(participants: participants.pluck(:id))
你有它。