Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何编写Rake任务将数据导入Rails应用程序?_Ruby On Rails_Ruby_Import_Cron_Rake - Fatal编程技术网

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

Ruby on rails 如何编写Rake任务将数据导入Rails应用程序?,ruby-on-rails,ruby,import,cron,rake,Ruby On Rails,Ruby,Import,Cron,Rake,目标:使用CRON任务(或其他预定事件)通过每晚从现有系统导出数据来更新数据库 在现有系统中创建/更新/删除所有数据。该网站不直接与该系统集成,因此rails应用程序只需反映数据导出中出现的更新 我有一个约5000种产品的.txt文件,如下所示: "1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222" "A134":"another product":"attr 1":"attr 2":"Foobar World":"

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

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

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

"1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222"
"A134":"another product":"attr 1":"attr 2":"Foobar World":"2447"
...
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
所有值都是用双引号(
)括起来的字符串,用冒号(
)分隔

字段包括:

  • id
    :唯一id;字母数字
  • 名称
    :产品名称;任意字符
  • 属性列:字符串;任意字符(例如大小、重量、颜色、尺寸)
  • 供应商名称
    :字符串;任意字符
  • 供应商id
    :唯一的供应商id;数字
供应商信息在当前系统中未规范化

这里的最佳实践是什么?删除products和vendors表并在每个周期中使用新数据重写可以吗?还是只添加新行并更新现有行更好

注意事项:

  • 此数据将用于生成通过夜间数据库导入持久化的
    订单
    订单项
    将需要连接到数据文件中指定的产品id,因此我们不能依赖于自动递增主键使每次导入都相同;需要使用唯一的字母数字id将
    产品
    加入
    订购项目
  • 理想情况下,我希望进口商规范化供应商数据
  • 我不能使用普通的SQL语句,所以我想我需要编写一个
    rake
    任务来使用
    Product.create(…)
    Vendor.create(…)
    风格的语法
  • 这将在EngineYard上实施

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

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

    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!
    
    p=Product.find\u或通过\u标识符初始化\u()
    p、 姓名=
    p、 尺寸=
    等
    p、 救命!
    
    find_或_initialize将根据您指定的id在数据库中查找产品,如果找不到,它将创建一个新的产品。这样做的真正方便之处在于,ActiveRecord只会在任何数据发生更改时保存到数据库中,并会自动更新表中的任何时间戳字段还有一件事,因为您将通过标识符(文件中的id)查找记录,所以我将确保在数据库中的该字段上添加索引

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

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

    "1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222"
    "A134":"another product":"attr 1":"attr 2":"Foobar World":"2447"
    ...
    
    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
    
    namespace:data do
    desc“将数据从文件导入数据库”
    任务:导入=>:环境执行
    file=file.open()
    文件。每个do |行|
    attrs=line.split(“:”)
    p=产品。查找\u或通过\u标识符初始化\u(属性[0])
    p、 name=attrs[1]
    等
    p、 救命!
    结束
    结束
    结束
    

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

    由于产品不会经常更改,因此我认为最好的方法是只更新更改的记录

  • 得到所有的三角洲
  • 使用单个SQL语句进行批量更新
  • 如果模型中有规范化代码,则可以使用Product.create和Vendor.create,否则就太过分了。此外,考虑在一个SQL事务中插入多个记录,速度会快得多。

    • 创建一个cronned的导入器rake任务
    • 使用更快的CSV或类似香草ruby的方式逐行解析文件:
    文件。每个do |行| products\u数组=行。拆分(“:”) 结束

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

      产品。通过名称和供应商id(“foo”,111)查找或初始化


    正如我在问题中提到的,我不能使用普通的SQL语句。为什么要使用
    find\u或\u initialize\u by\u name\u和\u vendor\u id
    ?这是否意味着产品
    接受:vendor
    的嵌套属性?我尝试过这一点,但我得到了错误
    未定义的局部变量或main:Object
    的方法“data”。有什么想法吗可能正在发生?问题是
    名称空间数据do
    必须更改为
    名称空间:数据do