1
votes

Insertion groupée ActiveRecord avec has_one

Avez-vous déjà résolu un problème d'insertion en masse d'enregistrements avec association imbriquée? (avec rails insert_all ou avec le gem import) exemple:

has_one :owner, class_name: Person

et

Dog.insert_all(array_of_dogs)

ne fonctionnera pas si un chien a une association de propriétaires

Dog.import!(array_of_dogs)

et espérant persister tous les chiens et tous leurs propriétaires.


0 commentaires

3 Réponses :


0
votes

Vous avez deux possibilités.

  1. Vous supprimez toutes les contraintes et insérez toutes les données et ajoutez la contrainte à la fin. Cela fonctionne car au moment de la sauvegarde, toutes les contraintes fonctionnaient et le feront après la récupération

  2. vous ne pouvez insérer qu'une table à la fois, vous créez donc un modèle ER de votre base de données, regardez quelles tables doivent être créées en premier afin que toutes les tables qui sont dans la hiérarchie ci-dessus puissent être créées avec une table partenaire déjà créée sans . Et ainsi de suite jusqu'à la fin. le modèle ER n'est pas absolument nécessaire, mais dans les grandes bases de données avec beaucoup de tables, il aide à maintenir l'ordre et avec le bon programme, vous pouvez déplacer les tables pour trouver le bon ordre de récupération.


0 commentaires

0
votes

Vous devrez insérer les associations séparément.

J'ai expliqué comment j'ai résolu ce problème dans mon blog - https://medium.com/@muralidharanashish/bulk-import-in-ruby-on-rails-8546fed74f4


0 commentaires

1
votes

Il existe un joyau appelé DutyFree qui simplifie ce genre de chose. Imaginez avoir un schéma avec trois tables pour les catégories, sous-catégories et restaurants:

Person.suggest_template

Ce joyau analyse intelligemment les associations has_many et appartient_to sur les modèles et, sur la base de ces relations, identifie comment enregistrer correctement chaque ligne importée dans toutes les tables de destination. Une création ou une mise à jour est effectuée en fonction du fait que les données existent déjà ou non, et c'est sur une base par table, donc si par exemple la catégorie était déjà là mais pas la sous-catégorie ou le restaurant, alors seules ces deux pièces seraient ajouté et associé à la catégorie appropriée.

Cet exemple spécifique peut être vu dans un test ici: https://github.com/lorint/duty_free/blob/master/spec/models/restaurant_reverse_spec.rb

Tout ce que vous auriez à faire pour votre exemple de chien et de personne est après avoir mis la gemme dans votre Gemfile et regroupé, ouvrez le bac / les rails c et essayez un exemple d'exportation avec:

Person.df_export

Il devrait automatiquement passer par le fichier appart_to en personne pour trouver le chien associé. (En passant, vous pouvez envisager de changer cette association pour que le nom appartienne soit dans Chien, et au lieu d'un has_one transforme-le en has_many pour qu'une personne puisse avoir plusieurs chiens. Mais c'est une autre histoire pour une autre fois. Et si vous deviez changez-le, il serait plus logique de faire Dog.df_export ou Dog.suggest_template.)

Si vous souhaitez personnaliser davantage les colonnes impliquées, demandez à la gemme de vous donner un modèle de démarrage qui peut être ajouté directement dans le modèle Personne avec:

___________     _____________     _____________
|Category |     |Subcategory|     |Restaurant |
|         |     |           |     |           |
|         |---->|belongs_to |---->|belongs_to |
|         |     |   Category|     |Subcategory|
|         |     |           |     |           |
¯¯¯¯¯¯¯¯¯¯¯     ¯¯¯¯¯¯¯¯¯¯¯¯¯     ¯¯¯¯¯¯¯¯¯¯¯¯¯

Le hachage IMPORT_TEMPLATE qu'il affiche contient des détails sur les colonnes que vous souhaitez rendre uniques, telles que l'adresse e-mail ou le numéro de téléphone de la personne, et peut-être l'anniversaire du chien ou autre.

J'espère que tout cela aide.


1 commentaires

a l'air super sympa, même si j'avoue ne pas pouvoir tester complètement la solution gardera cela à l'esprit pour le prochain défi MERCI!