代码之家  ›  专栏  ›  技术社区  ›  maček

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

  •  9
  • maček  · 技术社区  · 16 年前

    目标: 使用cron任务(或其他计划的事件)通过夜间从现有系统导出数据来更新数据库。

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

    我有一个 .txt 大约5000种产品的文件如下:

    "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 :字符串;任何字符
    • vendor_id :唯一供应商ID;数字

    当前系统中的供应商信息未规范化。

    这里的最佳实践是什么?是否可以删除产品和供应商表并在每个周期中用新数据重写?还是只添加新行并更新现有行更好?

    笔记:

    1. 此数据将用于生成 Orders 这将通过夜间数据库导入而持久。 OrderItems 将需要连接到数据文件中指定的产品ID,因此我们不能依赖自动递增的主键在每次导入时保持相同;需要使用唯一的字母数字ID来联接 products order_items .
    2. 理想情况下,我希望进口商规范化供应商数据
    3. 我不能使用普通的SQL语句,所以我想我需要编写一个 rake 要使用的任务 Product.create(...) Vendor.create(...) 样式语法。
    4. 这将在Engineyard上实现
    3 回复  |  直到 12 年前
        1
  •  14
  •   Charles Duffy    14 年前

    我不会在每个周期中删除产品和供应商表。这是Rails应用程序吗?如果是这样的话,会有一些非常好的活动记录帮助器可以帮你。

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

    p = Product.find_or_initialize_by_identifier(<id you get from file>)
    p.name = <name from file>
    p.size = <size from file>
    etc...
    p.save!
    

    “查找”或“初始化”将根据指定的ID查找数据库中的产品,如果找不到该产品,它将创建一个新的产品。这样做真正方便的一点是,ActiveRecord只会在任何数据发生更改时保存到数据库中,并且会自动更新表中的任何时间戳字段(相应地更新)。还有一件事,因为您将通过标识符(文件中的ID)查找记录,所以我将确保在数据库中添加该字段的索引。

    为了完成这个任务,我将在Rails应用程序的lib/tasks目录中添加一个rake文件。我们称之为data.rake。

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

    namespace :data do
      desc "import data from files to database"
      task :import => :environment do
        file = File.open(<file to import>)
        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”。

        2
  •  0
  •   Greg    16 年前

    由于产品不会经常改变,所以我认为最好的方法就是只更新那些改变的记录。

    1. 得到所有的三角洲
    2. 使用单个SQL语句进行批量更新

    如果模型中有规范化代码,则可以使用product.create和vendor.create,否则这将是一种过度杀伤力。另外,在一个SQL事务中插入多个记录的速度要快得多。

        3
  •  0
  •   nicholasklick    16 年前
    • 创建cronned导入程序rake任务
    • 使用更快的csv或类似于vanilla ruby的工具逐行分析文件:

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

    • 将“:”上的每一行拆分并推入哈希
    • 使用“查找”或“初始化”填充数据库,例如:

      product.find_or_initialize_by_name_and_vendor_id(“foo”,111)