web-dev-qa-db-fra.com

Comment ajouter de nouvelles données de base à la base de données Rails existante

Je travaille sur une application déjà déployée sur des systèmes de test et de transfert et sur divers postes de travail de développeurs. J'ai besoin d'ajouter des données de référence supplémentaires, mais je ne sais pas comment les ajouter.

La plupart des conseils indiquent utiliser seed.rb, mais si j'ai bien compris, il ne s'exécute qu'une fois, lorsque l'application est initialement déployée. Étant donné que nous ne souhaitons pas reconstruire les bases de tests et de stockage intermédiaire uniquement pour pouvoir ajouter une ligne de données de référence, existe-t-il un autre moyen d'ajouter les données?

Je pense utiliser une migration de base de données, est-ce la bonne approche?

Merci

20
toby

Structurez votre fichier seed.rb pour permettre la création et la mise à jour continues des données. Vous n'êtes pas limité à l'exécution d'un fichier de démarrage une seule fois. Si vous pensez qu'il n'est utilisé que pour le déploiement initial, vous perdrez la flexibilité qu'il peut offrir pour la définition des données de référence.

Un fichier de démarrage est juste Ruby, vous pouvez donc faire des choses comme:

user = User.find_or_initialize_by(email: '[email protected]')
user.name = 'Bob'
user.password = 'secret'
user.role = 'manager'
user.save!

Cela créera de nouvelles données s'il n'en existe pas ou les mettra à jour s'il en trouve.

Si vous structurez correctement votre fichier de base, vous pouvez également créer et mettre à jour des objets dépendants.

Je recommande d'utiliser la sauvegarde rapide pour vous assurer que des exceptions sont générées dans le cas où un objet ne peut pas être enregistré. C'est la méthode la plus simple pour déboguer la graine.

J'utilise seedbank gem pour structurer davantage mes données de semences, y compris les données de paramétrage par environnement, les semences dépendantes, etc.

Je ne recommande pas d'utiliser les migrations pour les données de départ. Il y a un manque de flexibilité (comment cibler les données de base sur un seul environnement, par exemple) et pas de véritable moyen de créer un ensemble de données réutilisable pouvant être exécuté à tout moment pour actualiser un environnement particulier. Vous disposerez également d'un ensemble de migrations sans référence à votre schéma et vous devrez créer de nouvelles migrations chaque fois que vous souhaitez générer de nouvelles données ou modifier les données actuelles.

29
nmott

Vous pouvez utiliser une migration, mais ce n'est pas l'option la plus sûre… .. Par exemple, vous ajoutez un enregistrement à une table via une migration, puis vous changez le schéma de cette table. Lorsque vous installerez l'application quelque part, vous ne pourrez pas exécuter rake db:migrate.

Les graines sont toujours recommandables car rake db:seed peut être exécuté sur un schéma complètement migré.

Si c'est juste pour un enregistrement, optez pour la console Rails.

2
Miotsu

Il est préférable d'utiliser une méthode idempotente comme celle-ci dans seed.rb ou une autre tâche appelée par seed.rb:

Contact.find_by_email("[email protected]") || Contact.create(email: "[email protected]", phone: "202-291-1970", created_by: "System")
# This saves you an update to the DB if the record already exists.

Ou similaire à @ nmott's: 

Contact.find_or_initialize_by_email("[email protected]").update_attributes(phone: "202-291-1970", created_by: "System")
# this performs an update regardless, but it may be useful if you want to reset your data.

ou utilisez assign_attributes au lieu de update_attributes si vous souhaitez attribuer plusieurs attributs avant de sauvegarder.

1
konyak

J'utilise le fichier de départ pour ajouter des instances à des tables nouvelles ou existantes tout le temps. Ma solution est simple. Je viens de commenter toutes les autres données de base du fichier db/seeds.rb afin que seules les nouvelles données de base soient du code actif. Puis lancez bin/rake db:seed

1
Steve Carey

J'ai fait quelque chose comme ça dans seed.rb

users_list = [
   {id: 1, name: "Diego", age: "25"},
   {id: 2, name: "Elano", age: "27"}
]

while !users_list.empty? do
  begin
    User.create(users_list)
  rescue
    users_list = users_list.drop(1) #removing the first if the id already exist.
  end
end

Si un élément de la liste avec l'id donné existe déjà, il renverra une exception. Nous le supprimerons et le réessayerons jusqu'à ce que le tableau users_list soit vide.

De cette façon, vous n'avez pas besoin de rechercher chaque objet avant de l'inclure, mais vous ne pourrez pas mettre à jour les valeurs déjà insérées comme dans le code @nmott.

0
Jaga Jugue

Au lieu de modifier seeds.db, que vous souhaiterez probablement utiliser pour créer de nouvelles bases de données, vous pouvez créer une tâche Rake personnalisée ( RailsCast # 66 Custom Rake Tasks ).

Vous pouvez créer autant de tâches Rake que vous le souhaitez. Par exemple, disons que vous avez deux serveurs, l'un exécutant la version 1.0 de votre application, l'autre exécutant la version 1.1 et que vous souhaitez mettre à niveau tous les deux vers la version 1.2. Ensuite, vous pouvez créer lib/tasks/1-0-to-1-2.rake et lib/tasks`1-1-to-1-2.rake étant donné que vous aurez peut-être besoin d'un code différent selon la version de votre application.

0
ehannes