'how to prepare csv data using associated model with missing values in rails

I'm trying to prepare a csv file which'll be generated from multiple tables. So I've my model setup like bellow

# Student
# attributes
:id, :name 

class Student < ActiveRecord::Base
  has_many :answers
end

# Question model
# attributes
:id, :question

class Question < ActiveRecord::Base
  has_many :answers
end

# Answer model
# attributes
:id, :question_id, :student_id, :answer

class Answer < ActiveRecord::Base
  belongs_to :question
  belongs_to :student
end

Now I want to prepare a csv file.The header of the csv file will be the actual question of the Question model sorted(by id) and then prepare the csv data accordingly from Answer modoel .Now student might not answers all the questions.So I need to set n/a if a student doesn't answer a particular question. Offcourse the questions are sorted by id and the answer is also sorted by question_id. The output will be.

what_is_you_name, how_old_are_you, what_is_your_hobby
monsur, 18, playing football
ranjon, n/a, gardening
n/a, n/a, running

I query the Answer model.Because some of the Student skipped few question therefor there are no answer object present that's why the answer is in wrong position.

what_is_you_name, how_old_are_you, what_is_your_hobby
monsur, 18, playing football
ranjon, gardening
alex,running 

So I need to set n/a if the particular student skipped a question . I can't figure it out how to solve this problem.



Solution 1:[1]

You could overwrite attribute ie. if Answer model has field age you could do sth like:

def age
  self.age || "n/a"
end

This should return age if it's present or "n/a" if it's nil.

If this does not solve your problem please provide a way how do you create CSV.

Solution 2:[2]

Ok after your explanation i came up with sth like this:

  1. Create default array default = ['n/a', 'n/a', 'n/a']
  2. You should add :question_id to .pluck like here: answers_arr = student.answers.order(question_id: :asc).pluck(:question_id, :answer) it gives you sth like [[1, "18"], [2, "playing football"]]
  3. Replace values in default array with values from pluck: answers_arr.each { |e| default[e[0] -1] = e[1] } so default should look like ["18", "playing football", "n/a"]

EDIT Here is a code from the comment below that solved problem:

response = [] 
all_response = [] 
qs_id = [1,2.3]

answers.each do |answer|
  qs_ids.each do |q_id|
    if answer.question_id == q_id
      response << answer.answer
    else 
      response << 'n/a'
    end 
    if qs_ids.last = q_id 
      all_response << response 
    end
  end 
end 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2