导入CSV时,如何处理与关联对应的行中的数据?

mar*_*ion 5 csv import ruby-on-rails ruby-on-rails-3

我正在关注导入CSV Railscast,它很直接.

问题是它只处理一个csv文件,该文件只包含1个文件中1个模型的信息.

说,我有一个CSV文件,我试图导入我的Listing模型.在每行/列表上,它有一个名为列的列Building,其中值实际上是该列表的构建属性的名称(即@listing.building.name).

如何在导入中处理这些情况?

这是Ryan在Railscast中获得的壁橱,Product在他的案例中就是模型:

def self.import(file)
  CSV.foreach(file.path, headers: true) do |row|
    product = find_by_id(row["id"]) || new
    product.attributes = row.to_hash.slice(*accessible_attributes)
    product.save!
  end
end
Run Code Online (Sandbox Code Playgroud)

所有发生的事情是他正在检查产品是否存在以及是否存在然后更新属性.如果没有,则创建一个新的.

在这种情况下不太确定如何处理关联...特别是考虑到需要发生的事情是在不存在关联记录的情况下,需要在此过程中创建它.

所以回到我building.name之前的例子,如果没有Building.find_by_name(name),那么它应该创建一个新的建筑记录.

思考?

jvn*_*ill 2

尝试这个

def self.import(file)
  CSV.foreach(file.path, headers: true) do |row|
    product = find_by_id(row["id"]) || new
    product.attributes = row.to_hash.slice(*accessible_attributes)
    product.save!

    building = product.buildings.find_by_name(row['building_name'])
    building ||= product.buildings.build
    building.attributes = row.to_hash.slice(*build_accessible_attributes)
    building.save!
  end
end
Run Code Online (Sandbox Code Playgroud)

更新:使用新的 Rails 3 方法更新了答案

def self.import(file)
  CSV.foreach(file.path, headers: true) do |row|
    product = where(id: row["id"])
      .first_or_create!(row.to_hash.slice(*accessible_attributes))

    product.buildings.where(name: row['building_name'])
      .first_or_create!(row.to_hash.slice(*building_accessible_attributes))
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 使用“first_or_create”而不是使用“find_or_create”已成为标准[Rails Active Record Query](http://guides.rubyonrails.org/active_record_querying.html#first_or_create) (2认同)