Comment écrire tâche Rake pour importer des données d'application Rails?
Objectif: à l'Aide d'une tâche CRON (ou d'un autre événement prévu) mise à jour de la base de données avec tous les soirs à l'exportation de données à partir d'un système existant.
Toutes les données est créé ou mis à jour ou supprimés dans un système existant. Le site n'est pas directement intégrer à ce système, de sorte que l'application rails simplement doit refléter les mises à jour apparaissent dans l'exportation de données.
J'ai un .txt
fichier de ~5 000 produits, qui ressemble à ceci:
"1234":"product name":"attr 1":"attr 2":"ABC Manufacturing":"2222"
"A134":"another product":"attr 1":"attr 2":"Foobar World":"2447"
...
Toutes les valeurs sont des chaînes de caractères entre guillemets ("
) qui sont séparés par des deux points (:
)
Champs sont:
id
: id unique; alphanumériquesname
: nom du produit; tout caractère- colonnes d'attributs: les chaînes de caractères; n'importe quel caractère (p. ex., taille, poids, couleur, dimension)
vendor_name
: string; tout caractèrevendor_id
: code fournisseur unique; numérique
Informations de fournisseur n'est pas normalisée dans le système actuel.
Quelles sont les meilleures pratiques? Est-il acceptable de supprimer les produits et les vendeurs de tables et de réécrire avec les nouvelles données sur chaque cycle? Ou est-il préférable de n'ajouter de nouvelles lignes et de mise à jour de celles existantes?
Notes:
- Ces données seront utilisées pour générer
Orders
qui perdurera à travers tous les soirs de la base de données des importations.OrderItems
aura besoin d'être connecté à l'id de produit qui sont spécifiés dans le fichier de données, de sorte que nous ne pouvons pas compter sur une incrémentation automatique de la clé primaire sera le même pour chaque importation; l'unique id alphanumérique devra être utilisé pour joindre lesproducts
àorder_items
. - Idéalement, j'aimerais que l'importateur afin de normaliser le Fournisseur de données
- Je ne peux pas utiliser de la vanille SQL, donc j'imagine que je vais avoir besoin d'écrire un
rake
tâche afin d'utiliserProduct.create(...)
etVendor.create(...)
la syntaxe de style. - Ce sera mis en œuvre sur EngineYard
OriginalL'auteur maček | 2010-07-27
Vous devez vous connecter pour publier un commentaire.
Je ne voudrais pas supprimer les produits et les vendeurs de tableaux sur chaque cycle. Est-ce une application rails? Si donc il y a vraiment de belle ActiveRecord aides qui leur seraient utiles pour vous.
Si vous avez un Produit actif d'enregistrement de modèle, vous pouvez le faire:
La find_or_initialize va rechercher le produit dans la base de données par l'id que vous spécifiez, et si il ne peut pas le trouver, il va créer un nouveau. Vraiment la chose à portée de main sur cette façon de faire, c'est qu'ActiveRecord ne enregistrer dans la base de données si les données ont changé, et il sera automatiquement mise à jour toutes les champs d'horodatage vous avez dans le tableau (updated_at) en conséquence. Une chose de plus, car vous seriez à la recherche des enregistrements par l'identifiant (id dans le fichier), je voudrais assurez-vous d'ajouter un index sur ce champ dans la base de données.
Pour faire une tâche rake pour ce faire, je voudrais ajouter un râteau fichier vers le répertoire lib/tâches répertoire de votre application rails. Nous allons l'appeler de données.râteau.
À l'intérieur des données.râteau, il ressemblerait à quelque chose comme ceci:
Que d'appeler la tâche rake, utiliser "le râteau de données:importation" de la ligne de commande.
undefined local variable or method 'data' for main:Object
. Toutes les pensées peuvent expliquer ce qui se passe?Le problème est que les
namespace data do
a dû être changé pournamespace :data do
.OriginalL'auteur smnirven
Puisque les Produits ne changent pas vraiment que, souvent, la meilleure façon dont je voudrais voir, c'est de mettre à jour uniquement les enregistrements de changement.
Si vous avez votre code de la normalisation dans les modèles, vous pouvez utiliser le Produit.créer et le Vendeur.créer ou d'autre ce serait juste un overkill. Aussi, Regardez dans l'insertion de plusieurs enregistrements dans une seule transaction SQL, est beaucoup plus rapide.
OriginalL'auteur Greg
fichier.chaque ne |ligne|
products_array = ligne.split(":")
fin
Utiliser un find_or_initialize pour remplir votre base de données tels que:
Produit.find_or_initialize_by_name_and_vendor_id("foo", 111)
find_or_initialize_by_name_and_vendor_id
? Est-ce à vous proposer un Produitaccepts_nested_attributes_for :vendor
?OriginalL'auteur nicholasklick