Techioz Blog

activerecord-import gemを使用した再帰的インポート: 関連付けによる has_many が機能しない

概要

「activerecord-import gem」を使用してCSVファイルをデータベースにインポートしようとしています。 私は次のモデルを持っています

require 'csv'
class Question < ApplicationRecord
    has_many :question_answers, dependent: :destroy
    has_many :answers, through: :question_answers
    belongs_to :category
    belongs_to :product
class Answer < ApplicationRecord
    has_many :question_answers, dependent: :destroy
    has_many :questions, through: :question_answers
 end
class QuestionAnswer < ApplicationRecord
    belongs_to :question
    belongs_to :answer
end

以下の方法は、CSV データを処理し、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

コードは質問を挿入しますが、その答えがないと、次のようなエラーが表示されます。

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

Heroku を使用しています

CSVサンプル

助けていただければ幸いです

解決策

CSV がどのようなものであるかが分からないと、これ以上解決するのは難しいかもしれませんが、エラーはおそらく次の行からのものです。

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

その行の後半の属性はおそらく問題ありません (value、pdf_parag、key、position、note がすべて回答テーブルの列であると仮定しています。そうでない場合は、さらに問題が発生する可能性があります。) しかし、そこから始めています。答え:answer_arr[0]。

アンサー レコードに回答 (またはanswer_id) 属性を設定しようとしていると考えられます。 Answer_arr[0] がインポートするデータの ID であると仮定すると、answer:answer_arr[0] を ID:answer_arr[0] に置き換えてみることができます。

ただし、データをインポートしている場合は、インポートから ID を除外し、Rails に新しい ID を設定させることを検討することもできます。一般に、フレームワークによる主キーの管理方法をオーバーライドしようとするのは得策ではありません。質問に基づいて作成した回答を保存すると、Rails が賢く外部キーを正しく設定します。インポートするデータの ID をどうしても保持する必要がある場合は、ID を新しい列に入れることを検討してください。

それが正しくない場合は、エラー トレースと CSV からのサンプル データを提供してください。