Rails 4 загрузка CSV в несколько моделей


Я пытаюсь загрузить csv-файл, содержащий данные, принадлежащие двум различным моделям: Project и PurchaseOrder. Я использую отношение has_many, :through между моделями.

У меня возникли проблемы с загрузкой. Я внес в белый список общие атрибуты в обоих контроллерах и включил accepts_nested_attributes в обе модели.

Вот мой код для чтения в csv.

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      project_hash = row.to_hash
      project = Project.where(project_name: project_hash["project_number"]).first
      if project.present?
        project.first.update_attributes(project_hash)
      else
        Project.create! (project_hash)
      end
      purchase_order = PurchaseOrder.where(po_number: project_hash["po_number"]).first
      if purchase_order.present?
        PurchaseOrder.create!
      end
У меня есть два вопроса/проблемы.
  1. Я не могу читать в атрибуте po_number. Я получаю эту ошибку unknown attribute 'po_number' for Project.

  2. Я не знаю, как поместить созданный заказ на покупку в хэш проекта, чтобы он обновил вложенное значение атрибута.

Заранее спасибо всем, кто может помочь!

**** обновление С помощью этого метода данные сохраняются в правильные таблицы. Однако связь между покупкой заказа и проектом не сохраняется. Есть какие-нибудь мысли?

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      project_hash = row.to_hash
      po_hash = {}
      po = PurchaseOrder.new
      project_hash.each { |k, v| po_hash[k] = project_hash.delete(k) if po.respond_to?(k) }    

      project = Project.where(project_name: project_hash["project_number"]).first
      if project.present?
        project.first.update_attributes(project_hash)
      else
        Project.create! (project_hash)
      end

      po = PurchaseOrder.where(po_number: po_hash["po_number"]).first
      if po.present?
        po.first.update_attributes(po_hash)
      else
        PurchaseOrder.create! (po_hash)
      end
    end
  end
1 3

1 ответ:

Эти строки пытаются обновить / создать проект, используя все значения в хэше...

project.first.update_attributes(project_hash)
...
Project.create! (project_hash)

Но очевидно, что некоторые хэш-элементы (такие как "po_number") не имеют столбцов в таблице проектов.

Вам нужно разделить элементы хэша csv на основе того, какие элементы принадлежат к какой модели...

Например

po_hash = {}
po = PurchaseOrder.new
project_hash.each { |k, v| po_hash[k] = project_hash.delete(k) if po.respond_to?(k) }

Это позволит удалить поля заказа на покупку из project_hash и добавить их в po_hash, чтобы вы могли использовать правильный хэш для обновления правильного стол.

Для создания ассоциации...

Изменение

Project.create!(project_hash)

В

project = Project.create!(project_hash)

Таким образом, независимо от того, существует ли проект или создается заново, он хранится в переменной "project". Аналогично, сделайте

po = PurchaseOrder.create!(po_hash) 

Затем, после того как вы создали или обновили заказ на покупку, вы можете просто назначить po проекту...

project.purchase_orders << po