Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

retrieving multiple association data with conditions

I've been a programmer for a few years (I've mainly used PHP / CakePHP) but I'm new to Ruby on Rails.

I have a question regarding retrieving data for multiple associations with conditions.

I have the following four models:

class Questionnaire < ApplicationRecord
  has_many :sections
end

class Section < ApplicationRecord
  belongs_to :questionnaire
  has_many :questions
  has_many :non_questions

  def elements
    (questions + non_questions).sort_by(&:order)
  end

end

class Question < ApplicationRecord
  belongs_to :section

  validates_date :starts_on, allow_blank: true
  validates_date :expires_on, allow_blank: true
end

class NonQuestion < ApplicationRecord
    belongs_to :section
end

I currently want to show the whole questionnaire in the view - that is all the sections with their questions and non_questions in one page and in the right order. I would also like to pass a date parameter from the view, which will be used to retrieve the corresponding active questions only, based on the starts_on and expires_on date columns.

Using CakePHP, I would preload and store all the data in a variable in my model by using Left Joins with conditions. I tried to do something similar with rails (using all possible combinations of joins, includes, left_outer_joins) with a where condition, but when I, for example, call questionnaire.sections.first.elements it runs a new query without applying my condition. Am I missing something out? Is there a "right", ruby way to do something like this? Or given what my application requires, is there a better way to approach this?

Thanks in advance

like image 844
Thanos Avatar asked Apr 12 '26 19:04

Thanos


1 Answers

For eager loader in rails, you use includes. For your models, for example, you could do something like:

Questionnaire.includes(sections: [:questions, :non_questions]).references(:question).where("(questions.exp‌​ires_on >= :time OR questions.expires_on IS NULL) AND (questions.starts_on IS NULL OR questionsstarts_on <= :time)" , time: Time.now) 

If you want to access that set of records you retrieved multiple times, you should assign then to some variable, so it doesn't make a new query on db. Hope it enlightened your question

like image 171
Ronan Lopes Avatar answered Apr 14 '26 08:04

Ronan Lopes