如何编写Rake任务将数据导入Rails应用程序?

目标:使用CRON任务(或其他预定事件)通过从现有系统每晚导出数据来更新数据库。

在现有系统中创建/更新/删除所有数据。 该网站没有直接与该系统集成,因此rails应用程序只需要反映数据导出中出现的更新。

我有一个.txt产品的.txt文件,如下所示:

 "1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222" "A134":"another product":"attr 1":"attr 2":"Foobar World":"2447" ... 

所有值都是用双引号( " )括起来的字符串,用冒号(:)分隔

领域是:

  • id :唯一ID; 字母
  • name :产品名称; 任何角色
  • 属性列:字符串; 任何字符(例如,大小,重量,颜色,尺寸)
  • vendor_name :string; 任何角色
  • vendor_id :唯一供应商ID; 数字

供应商信息在当前系统中未标准化。

这里的最佳做法是什么? 是否可以删除产品和供应商表并在每个周期重写新数据? 或者仅添加新行并更新现有行更好?

笔记:

  1. 此数据将用于生成将通过夜间数据库导入持续存在的OrdersOrderItems需要连接到数据文件中指定的产品ID,因此我们不能依赖自动递增的主键对于每个导入都是相同的; 需要使用唯一的字母数字ID将products加入order_items
  2. 理想情况下,我希望导入器规范化供应商数据
  3. 我不能使用vanilla SQL语句,所以我想我需要编写一个rake任务才能使用Product.create(...)Vendor.create(...)样式语法。
  4. 这将在EngineYard上实现

我不会在每个周期删除产品和供应商表。 这是一个rails应用程序吗? 如果是这样,有一些非常好的ActiveRecord助手可以为您派上用场。

如果您有产品活动记录模型,则可以执行以下操作:

 p = Product.find_or_initialize_by_identifier() p.name =  p.size =  etc... p.save! 

find_or_initialize将按您指定的ID在数据库中查找产品,如果找不到,则会创建一个新产品。 这样做非常方便的事情是,ActiveRecord只会在任何数据发生变化时保存到数据库,并且会相应地自动更新表中的任何时间戳字段(updated_at)。 还有一件事,因为您将通过标识符(文件中的id)查找记录,我将确保在数据库中的该字段上添加索引。

要完成rake任务,我会将rake文件添加到rails应用程序的lib / tasks目录中。 我们称之为data.rake。

在data.rake里面,它看起来像这样:

 namespace :data do desc "import data from files to database" task :import => :environment do file = File.open() file.each do |line| attrs = line.split(":") p = Product.find_or_initialize_by_identifier(attrs[0]) p.name = attrs[1] etc... p.save! end end end 

要调用rake任务,请从命令行使用“rake data:import”。

由于产品实际上并没有真正改变,我看到的最好的方法是只更新改变的记录。

  1. 获得所有的增量
  2. 使用单个SQL语句进行批量更新

如果你在模型中有规范化代码,你可以使用Product.create和Vendor.create,否则它只是一个矫枉过正。 另外,查看在单个SQL事务中插入多个记录,其速度要快得多。

  • 创建一个cronned的导入器rake任务
  • 使用Faster CSV或vanilla ruby​​逐行解析文件,如:

file.each do | line | products_array = line.split(“:”)结束

  • 拆分“:”上的每一行并插入哈希
  • 使用find_or_initialize填充数据库,例如:

    Product.find_or_initialize_by_name_and_vendor_id(“foo”,111)