1

I am fairly new to rails. I have the following models

class Question < ActiveRecord::Base
  has_many :options
  has_many :response_parts
end

class ResponsePart < ActiveRecord::Base
  belongs_to :question
end

The corresponding scaffolds are

rails g scaffold Question qorder:string qtext:text qtype:string

rails g scaffold ResponsePart answer:string question:belongs_to

Now I want all the response parts where qtype is 'mobile'. I have tried a few ways but could not query successfully. Can someone tell a way to make such query. Thanks in advance.

Peeyush
  • 6,144
  • 5
  • 23
  • 37

3 Answers3

0

Try:

Question.where(qtype: 'mobile').collect(&:response_parts)

This will give you all the response_parts for all the questions with qtype = 'mobile'

Update: (Avoiding N+1 queries)

Question.where(qtype: 'mobile').collect(&:response_parts)

This will execute a select query on each response_parts for each question leading to the "N+1" queries.

In order to avoid "N+1 queries" i.e. one Query to retrieve question and n queries to retrieve resposne_parts, you can add includes(:join_relation) (where :join_relation is response_parts in your case) as follows:

Question.includes(:response_parts).where(qtype: 'mobile').collect(&:response_parts)
vee
  • 38,255
  • 7
  • 74
  • 78
  • This is not optimized, if there is X Question where `qtype == 'mobile'`, it will generate X SQL queries to retrieve them. (The famous N+1 Queries: http://stackoverflow.com/questions/5452340/preventing-n1-queries-in-rails) – MrYoshiji Dec 24 '13 at 16:31
  • Thanks @MrYoshiji, I've updated my answer to address the "N+1" queries issue. – vee Dec 24 '13 at 16:38
0

try this

Question.where(qtype: "mobile").first.response_parts
Nitin Jain
  • 3,053
  • 2
  • 24
  • 36
0

You can include the relation between the two model and add a constraint on it:

ResponsePart.includes(:question).where(questions: { qtype: 'mobile' })

This will retrieve all the ResponsePart objects from the DB having a question which match "qtype == 'mobile'"

This is also the most efficient way to retrieve these records.


Question.where(qtype: 'mobile').collect(&:response_parts)

This will query the DB to get the corresponding response_parts of each question having "qtype == 'mobile'" Example: If you have 6 questions with "qtype == 'mobile'", it will create 6 SQL queries for each Question.

Question.where(qtype: "mobile").first.response_parts

This just retrieves the ResponsePart objects related to the first question matching the condition "qtype == 'mobile'"

MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • Thanks. I get ` #, #]>` when I query `ResponsePart.includes(:question).where(questions: { qtype: 'mobile' })`. But now I want to access the corresponding answer values. When I use 'ResponsePart.includes(:question).where(questions: { qtype: 'mobile' }).each and try to access the values using .answer it gives an error undefined method `answer`. Am I accessing the values incorrectly? – Peeyush Dec 24 '13 at 16:44
  • Hmm that would concern another question, but we can answer it here. Make sure you are using the right variable: in your view, you should have something like `ResponsePart.includes(:question).where(questions: { qtype: 'mobile' }).each do |response_part|` then you should be able to access the answer value by doing `response_part.answer` in the block of the .each iterator --- If you don't understand this, I need to know what you're using in your views: HAML or ERB? Then I'll show you an example – MrYoshiji Dec 24 '13 at 16:46