2016-05-13 76 views
0

我正在使用ActiveRecord的rails项目。我正在做一些循序渐进的查询,由于我是Activerecord的新手,似乎缺少关键概念。我无法在模型上获得标识,因此无法执行查询。这里是我的代码:无法获得RoR Active记录模型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

它看起来像你的变量'参与者'是一个集合的集合。此链接可能会帮助您:http://stackoverflow.com/questions/27021036/undefined-method-id-for-activerecordrelation – Pholochtairze

回答

0

@ Pholochtairze的答案是当场上。这个答案是删除所有这些电话来映射,并有效地得到你需要的所有答案(双关语意:p)

首先你会得到所选答案的列表。我们将把所有标题保存到一个不同的变量中,并用它来获得所有的答案。我们还将使用flat_map作为最外层循环。与flatten!!方法

questions = JSON.parse(q) 

titles = questions.flat_map do |ques| 
    ques['options'].map { |opt| opt['title'] } 
end 

selected_answers = Answer.where(value: titles) 

一个问题是,他们返回零的时候没有做,因为你通常不希望在链使用它们的变化。因此,这里的重构是将的呼叫转移到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)) 

而你有它。

0

看起来participants是集合的集合。你正在使用map,所以你的变量p现在是一个集合(实际上Participant::ActiveRecord_Relation告诉你它是一个集合),这就是为什么它没有id

stats[:answers] = participants.map do |p| 
    p.map do |p1| 
    Answer.where(participants: p1.id) 
    end 
end 

您可以在这里找到一个相关的问题:我要再次通过收集(在p一个这一次)如下尝试循环undefined method `id' for #<ActiveRecord::Relation []>

0

,因为你做了地图它不工作它构造一个数组其中也返回数组相结合,让你有数组的数组:

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)