导入CSV时选择字段

时间:2014-08-04 15:38:09

标签: ruby-on-rails

我的Miniatures模型中有以下CSV导入操作

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      Miniature.create! row.to_hash
    end
  end

工作正常,但我想要做的是使用CSV中的其他列来创建关联对象。

这是我的一次尝试:

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      Miniature.create! row.to_hash.slice(row[0..10])
      @miniature.sizes.build(:scale_id => row[11])
    end
  end

我尝试切割行非常不成功。如果我没有切掉前10行,那么Miniature.create会尝试解析仅适用于关联大小模型的第11列。我想切掉前10个并用它们创建一个Miniature对象,然后使用提供的scale_id在我的Sizes连接表中构建或创建一行。

非常感谢任何帮助。

另一次更新

这是我最新,最干净的尝试:

Miniature.create! row.to_hash.except!(:scale_id)

将“unknown attribute:scale_id”作为错误抛出。可能我在CSV.foreach(file.path, headers: true) do |row|之后根本无法与密钥交互?

再次更新

我可以看到上述代码无效的原因之一。我正在为行中的字段指定范围,但哈希没有订单。我现在尝试使用索引指定我想要处理的键,但是使用了未定义的方法'indices'。

row.to_hash.indices(:name,:material,:release_date,:pcode,:notes,:set,:random,:quantity,:date_mask,:multipart)

我无法将其转换为数组或者我会得到字符串键错误但我需要能够指定创建操作应该使用哪些字段,以便我可以使用一些用于Miniature创建,一些用于Size创建

我的控制器动作如下:

def import
    Miniature.import(params[:file])
    redirect_to miniatures_path, notice: "Miniatures imported."
end

更新

以下是我用来导入的种子数据

  

名称,材料,RELEASE_DATE,P码,票据,集,随机,数量,date_mask,多部分,scale_id

     

A A A CSV测试,金属,03/01 / 2013,123123,测试笔记,f,f ,, 6,f,1

使用上面的代码,我得到的错误是

  

“验证失败:名称不能为空,材料不能为空”

但是通过尝试,我遇到了各种各样的错误,这些错误表明我的row.to_hash.slice没有像更简单的row.to_hash那样被解析。

预期的结果是成功创建的Miniature对象和Size对象,或者创建size对象时出错,因为它无法从我使用的@ miniature.sizes.build推断出tiny_id并想要更多的参数。在初始切片阶段被传递/解析之前无法调试。

1 个答案:

答案 0 :(得分:2)

您假设哈希的键是:scale_id之类的符号,但实际上它们像'scale_id'那样是字符串,这就是您绊倒的地方..如果要将它们用作创建方法的属性,则需要对键进行符号化。

symbolized_row = row.to_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
Miniature.create! symbolized_row.except!(:scale_id)

修改

实际上,如果您使用except代替变异except!,那么您可以访问后续行中的比例ID。

symbolized_row = row.to_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
Miniature.create! symbolized_row.except(:scale_id)
@miniature.sizes.build(:scale_id => symbolized_row[:scale_id])