使用Ruby on Rails从FTP下载CSV文件并更新现有记录

时间:2017-10-19 21:56:23

标签: ruby-on-rails ruby csv ftp

我正在尝试从FTP服务器下载CSV文件,如果记录存在,我想更新该记录而不创建副本。为了提供更多上下文 - 我正在尝试将一组FTP文件夹中的订单上传到我的Rails应用程序中。每小时都有一个新文件 - 有时某个订单中的订单包含前一个订单中的重复项,以防止客户滑过轨道或有时客户更新订单(更改数量,更改地址等) 。)下一滴。所以我的问题是,如果订单纯粹是重复而没有更改,我如何跳过这些订单,如果记录已更改,我该如何更新该记录?

Ruby on Rails 5.1.4 - Ruby 2.4.1

谢谢!

以下代码来自我的模型:

class Geek < ApplicationRecord
require 'csv' 

def self.download_walmart_orders(out)
    out ||= "#{Rails.root}/test_orders.csv"   
        CSV.foreach(out, :headers => true,
                  :converters => :all,
                  :header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
                  ) do |row|
   geek = Geek.where(customer_order_id: row.to_h["customer_order_id"], 
                                     customer_name: row.to_h["customer_name"],
                                     item_sku: row.to_h["item_sku"],
                                     quantity_to_ship: row.to_h["quantity_to_ship"],
                                     total_items_price: row.to_h["total_items_price"]).first_or_create
    puts geek
end     
end

1 个答案:

答案 0 :(得分:2)

我假设customer_order_id是唯一的。

你可以尝试这样的事情 -

   def self.update_or_create(attributes)
     assign_or_new(attributes).save
   end


   Geek.where(customer_order_id: row.to_h["customer_order_id"]).update_or_create.( 
                                 customer_name: row.to_h["customer_name"],
                                 item_sku: row.to_h["item_sku"],
                                 quantity_to_ship: row.to_h["quantity_to_ship"],
                                 total_items_price: row.to_h["total_items_price"])

^^^谢谢Michael,上面的方向。我最终使用这个代码,它完美地工作。 (对于略有不同的项目,但完全相同的用例)我的最终模型代码如下:

class Wheel < ApplicationRecord
require 'csv'

def self.update_or_create(attributes)
  obj = first || new
  obj.assign_attributes(attributes)
  obj.save!
end

def self.import(out)
    out ||= "#{Rails.root}/public/300-RRW Daily Inv Report.csv"
        CSV.foreach(out, :headers => true,
                  :converters => :all,
                  :header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
                  ) do |row|
     Wheel.where(item: row.to_h["item"]).update_or_create(
                                     item_desc: row.to_h["item_desc"],
                                     total_quantity: row.to_h["total_quantity"])
  end
end