2017-10-19 21 views
0

J'essaie de télécharger un fichier CSV à partir d'un serveur FTP et si l'enregistrement existe, je veux mettre à jour cet enregistrement et ne pas créer un doublon. Pour donner un peu plus de contexte - j'essaie de télécharger un groupe de commandes à partir d'un dossier FTP dans mon application Rails. Il y a un nouveau fichier toutes les heures - parfois les commandes d'une certaine liste contiennent des doublons de la précédente pour éviter de glisser sur les pistes ou à l'occasion la commande a été mise à jour par le client (changement de quantité, changement d'adresse, etc. .) w/la prochaine baisse. Donc, ma question est de savoir si la commande est purement un doublon sans modifications, comment puis-je passer au-dessus de ces commandes et si un enregistrement a été modifié, comment puis-je mettre à jour cet enregistrement?Télécharger un fichier CSV à partir de FTP avec Ruby on Rails et mettre à jour des enregistrements existants

Ruby on Rails 5.1.4 - Ruby 2.4.1

Merci!

Le code ci-dessous est de mon modèle:

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 

fin

+1

sons assez cool. Avez-vous une question? – jvillian

+0

Dans Rails 5, vous voulez utiliser ['find_or_create_by'] (http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by). – max

+0

Salut jvillian, je m'excuse pour le phrasé pauvre J'ai juste édité la question en espérant fournir un peu plus de clarté sur ma question. Salut Max - il semble que ça marchera bien pour apporter les données si je n'ai pas de mises à jour. Pour un enregistrement existant Que dois-je utiliser si j'ai effectivement besoin de mettre à jour un enregistrement existant? (La question est reformulée en haut pour donner un meilleur exemple) –

Répondre

2

Je suppose que customer_order_id est unique.

Vous pouvez essayer quelque chose comme ça -

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"]) 

^^^ Merci, Michael, pour la direction ci-dessus. J'ai fini par utiliser ce code et cela a parfaitement fonctionné. (Pour un projet légèrement différent, mais même cas d'utilisation exacte) mon code modèle est finalisé ci-dessous:

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 

fin

+0

Ceci me conduit définitivement dans la bonne direction. Merci, Michael, pour toute l'aide! –

+0

Content de pouvoir aider! :) S'il vous plaît acceptez la réponse s'il est bon d'y aller: D –