import with recursive using activerecord-import gem: has_many through association not working

1.7k views Asked by At

Trying to import CSV file to the database using "activerecord-import gem". I have the following Models

question.rb

require 'csv'
class Question < ApplicationRecord
    has_many :question_answers, dependent: :destroy
    has_many :answers, through: :question_answers
    belongs_to :category
    belongs_to :product

answer.rb

class Answer < ApplicationRecord
    has_many :question_answers, dependent: :destroy
    has_many :questions, through: :question_answers
 end

question_answer.rb

class QuestionAnswer < ApplicationRecord
    belongs_to :question
    belongs_to :answer
end

The below method is to handle the CSV data and prepare it to be saved using ActiveRecord import gem

def self.from_csv(file)
        questions = []
        CSV.foreach(file.path, headers: true) do |row|
            category = Category.find_by(name: row['category'].strip)
            product = Product.find_by(title: row['product'].strip)
            parent_q = Question.find_by(qname: row['parent'])
            question = Question.new(
                question: row['question'],
                qtype: row['qtype'],
                tooltip: row['tooltip'],
                parent: parent_q,
                position: row['position'],
                qname: row['qname'],
                category_id: category.id,
                product_id: product.id,
                state_id: row['state_id'],
                explanation: row['explanation']

            )
            answers = row['answers'].split(" | ") if row['answers'].present?

            if answers.present?
                answers.each do |a_str|
                    answer_arr = a_str.split(',')
                    question.answers.build(answer: answer_arr[0] || "", value: answer_arr[1] || "", pdf_parag: answer_arr[2] || "", key: answer_arr[3] || "", position: answer_arr[4] || "", note: answer_arr[5] || "")
                end
            end
            p question.answers.inspect
            questions << question
        end
        imported_obj = Question.import questions, recursive: true, validate: false
    end

the code insert questions but without their answers, it gives an error saying:

NoMethodError (undefined method `answer_id=' for #<Answer:0x000000000>

I'm using Heroku

Update 1

CSV Sample

enter image description here

any help is highly appreciated

2

There are 2 answers

3
Glyoko On

Without knowing what you csv looks like it might be hard to help more, but the error is probably from the line:

question.answers.build(answer: answer_arr[0], ...)

The latter attributes in that line are probably ok, (I'm assuming value, pdf_parag, key, position, and note are all columns on the answers table. If that's not true you may have further problems.) but you're starting that with answer: answer_arr[0].

It thinks you're trying to set the answer (or answer_id) attribute on an answer record. Assuming answer_arr[0] is meant to be the id of the data you're importing, you could try replacing answer: answer_arr[0] with id: answer_arr[0].

However, if you're importing data, you may want to consider leaving ids out of the import and let rails set new ids for you. Generally speaking it's a bad idea to try to override how your frameworks manage primary keys. Once you save the answers you built on the questions, Rails will be smart and set your foreign keys correctly. If you absolutely need to preserve the ids from the data you're importing, consider putting them in a new column.

If that's not correct then please provide the error trace and give some sample data from the csv.

0
Alexander Senko On

Looks like ActiveRecord::Import doesn't support has_many :through associations yet, neither does it even have a ticket for that.

The best way to resolve the issue is, IMO, to add the support to ActiveRecord::Import itself.