Ruby on rails Ruby:如果列存在,则使用它,如果不存在,则添加到其他列
我正在解析CSV并试图区分模型中的列和将添加到JSONB:data列的虚拟列。到目前为止,我得到了这个:Ruby on rails Ruby:如果列存在,则使用它,如果不存在,则添加到其他列,ruby-on-rails,csv,ruby-on-rails-4,jsonb,smartercsv,Ruby On Rails,Csv,Ruby On Rails 4,Jsonb,Smartercsv,我正在解析CSV并试图区分模型中的列和将添加到JSONB:data列的虚拟列。到目前为止,我得到了这个: rows = SmarterCSV.process(csv.path) rows.each do |row| row.select! { |x| Model.attribute_method?(x) } # this ignores non-matches Model.create(row) end 从CSV行中删除与模型不匹配的列。相反,我想将所有这些数据添加到模型中名为:dat
rows = SmarterCSV.process(csv.path)
rows.each do |row|
row.select! { |x| Model.attribute_method?(x) } # this ignores non-matches
Model.create(row)
end
从CSV行中删除与模型不匹配的列。相反,我想将所有这些数据添加到模型中名为:data的列中。我该怎么做
编辑
像这样的选择之前!也许吧
您是否尝试过:
row[:data] = row.delete_if {|k,v| !Model.attribute_method?(k) }
Model.create(row)
这将从行哈希中删除元素,并将键值对添加回:data key下的行。您可以尝试使用此has\u属性吗
有很多方法可以做到这一点。一个特别简单的方法是使用Rails的ActiveSupport扩展,它的工作原理类似于Arrayslice!并返回一个散列,其中包含参数中未给定的键,同时保留给定的键:
rows = SmarterCSV.process(csv.path)
attrs = Model.attribute_names.map(&:to_sym)
rows.each do |row|
row[:data] = row.slice!(*attrs)
Model.create(row)
end
另外,这可能是用愚蠢的Ruby技巧写的,但是如果你使用Ruby 2.0+你可以利用双splat**来实现这个紧凑的结构:
rows.each do |row|
Model.create(data: row.slice!(*attrs), **row)
end
p.p.S.如果您的CSV很大,并且您发现自己在调用create数千次后出现性能问题,并且后续的数据库插入并不便宜,那么我建议您检查一下。它正是为这类事情而设计的。使用它,您可以执行以下操作:
rows = SmarterCSV.process(csv.path)
attrs = Model.attribute_names.map(&:to_sym)
models = rows.map do |row|
row[:data] = row.slice!(*attrs)
Model.new(row)
end
Model.import(models)
activerecord导入文档中还有其他更快的选项。我喜欢keep\u if,但有\u属性?对我不起作用。rails 3.2+它会起作用的,或者那是一个dope one liner!谢谢很乐意帮忙!我添加了一个关于宝石的注释,你可能会发现它很有用;看一看,不是你第一次参加牛仔竞技表演吧?非常感谢。
rows.each do |row|
Model.create(data: row.slice!(*attrs), **row)
end
rows = SmarterCSV.process(csv.path)
attrs = Model.attribute_names.map(&:to_sym)
models = rows.map do |row|
row[:data] = row.slice!(*attrs)
Model.new(row)
end
Model.import(models)