web-dev-qa-db-fra.com

Comment (et s'il faut) remplir Rails application avec les données initiales

J'ai une application Rails où les utilisateurs doivent se connecter. Par conséquent, pour que l'application soit utilisable, il doit y avoir un utilisateur initial dans le système pour que la première personne puisse se connecter avec (ils peuvent ensuite créer des utilisateurs ultérieurs.) Jusqu'à présent, j'ai utilisé une migration pour ajouter un utilisateur spécial à la base de données.

Après avoir demandé cette question , il semble que je devrais utiliser db: schema: load, plutôt que d'exécuter les migrations, pour configurer de nouvelles bases de données sur de nouvelles machines de développement. Malheureusement, cela ne semble pas inclure les migrations qui insèrent des données, seulement celles qui configurent des tables, des clés, etc.

Ma question est, quelle est la meilleure façon de gérer cette situation:

  1. Existe-t-il un moyen d'obtenir d: s: l pour inclure les migrations d'insertion de données?
  2. Ne devrais-je pas du tout utiliser les migrations pour insérer des données de cette façon?
  3. Ne devrais-je pas du tout pré-remplir la base de données avec des données? Dois-je mettre à jour le code de l'application afin qu'il gère le cas où il n'y a pas d'utilisateurs avec élégance et permet de créer un compte d'utilisateur initial en direct à partir de l'application?
  4. D'autres options? :)
61
Luke Halliwell

Je pensais que je résumerais certaines des bonnes réponses que j'ai eues à cette question, ainsi que mes propres pensées maintenant je les ai toutes lues :)

Il y a deux problèmes distincts ici:

  1. Dois-je pré-remplir la base de données avec mon utilisateur spécial "admin"? Ou l'application devrait-elle fournir un moyen de s'installer lors de sa première utilisation?
  2. Comment préremplir la base de données avec des données? Notez que c'est une question valide quelle que soit la réponse à la partie 1: il existe d'autres scénarios d'utilisation pour la pré-population qu'un utilisateur administrateur.

Pour (1), il semble que la configuration du premier utilisateur à partir de l'application elle-même soit un travail supplémentaire, pour des fonctionnalités qui, par définition, sont rarement utilisées. Cependant, il peut être légèrement plus sécurisé, car il oblige l'utilisateur à définir un mot de passe de son choix. La meilleure solution se situe entre ces deux extrêmes: avoir un script (ou tâche de râteau, ou autre) pour configurer l'utilisateur initial. Le script peut ensuite être configuré pour se remplir automatiquement avec un mot de passe par défaut pendant le développement et pour exiger la saisie d'un mot de passe pendant l'installation/le déploiement de la production (si vous souhaitez décourager un mot de passe par défaut pour l'administrateur).

Pour (2), il semble qu'il existe un certain nombre de bonnes solutions valables. Une tâche de rake semble être un bon moyen, et il existe des plugins pour rendre cela encore plus facile. Il suffit de parcourir certaines des autres réponses pour voir les détails de celles-ci :)

4
Luke Halliwell

Essayez une tâche de râteau. Par exemple:

  1. Créez le fichier / lib/tasks/bootstrap.rake
  2. Dans le fichier, ajoutez une tâche pour créer votre utilisateur par défaut:

    namespace :bootstrap do
      desc "Add the default user"
      task :default_user => :environment do
        User.create( :name => 'default', :password => 'password' )
      end

      desc "Create the default comment"
      task :default_comment => :environment do
        Comment.create( :title => 'Title', :body => 'First post!' )
      end

      desc "Run all bootstrapping tasks"
      task :all => [:default_user, :default_comment]
    end
  1. Ensuite, lorsque vous configurez votre application pour la première fois, vous pouvez faire rake db: migrate OR rake db: schema: load, puis faire rake bootstrap: all.
46
Aaron Wheeler

Utilisez db/seed.rb présent dans toutes les applications Rails.

Alors que certaines réponses données ci-dessus de 2008 peuvent bien fonctionner, elles sont assez obsolètes et elles ne sont plus vraiment Rails convention).

Le remplissage des données initiales dans la base de données doit être effectué avec le fichier db/seed.rb.

Cela fonctionne comme un fichier Ruby.

Pour créer et enregistrer un objet, vous pouvez faire quelque chose comme:

User.create(:username => "moot", :description => "king of /b/")

Une fois que ce fichier est prêt, vous pouvez suivre

rake db:migrate

rake db:seed

Ou en une seule étape

rake db:setup

Votre base de données doit être remplie avec les objets que vous souhaitez créer dans seed.rb

34
Jason Kim

Je vous recommande de ne pas insérer de nouvelles données dans les migrations. Au lieu de cela, modifiez uniquement les données existantes dans les migrations.

Pour insérer des données initiales, je vous recommande d'utiliser YML. Dans chaque projet Rails que je configure, je crée un répertoire fixtures sous le répertoire DB. Ensuite, je crée des fichiers YML pour les données initiales tout comme les fichiers YML sont utilisés pour les données de test. Ensuite, j'ajoute un nouvelle tâche pour charger les données à partir des fichiers YML.

lib/tasks/db.rake:

namespace :db do
  desc "This loads the development data."
  task :seed => :environment do
    require 'active_record/fixtures'
    Dir.glob(Rails_ROOT + '/db/fixtures/*.yml').each do |file|
      base_name = File.basename(file, '.*')
      say "Loading #{base_name}..."
      Fixtures.create_fixtures('db/fixtures', base_name)
    end
  end

  desc "This drops the db, builds the db, and seeds the data."
  task :reseed => [:environment, 'db:reset', 'db:seed']
end

db/fixtures/users.yml:

test:
  customer_id: 1
  name: "Test Guy"
  email: "[email protected]"
  hashed_password: "656fc0b1c1d1681840816c68e1640f640c6ded12"
  salt: "188227600.754087929365988"
32
Jay Stramel

Ceci est ma nouvelle solution préférée, en utilisant les gemmes populator et faker:

http://railscasts.com/episodes/126-populating-a-database

9
Mark Richman

Essayez le plugin seed-f , qui est un plugin assez simple qui vous permet de semer des données (et de changer ces données de semence à l'avenir), vous permettra également de semer des données spécifiques à l'environnement et des données pour tous les environnements .

6
DEfusion

Je suppose que la meilleure option est le numéro 3, principalement parce que de cette façon, il n'y aura pas d'utilisateur par défaut, ce qui est un excellent moyen de rendre inutile une bonne sécurité.

4
Vinko Vrsalovic

Pensez à utiliser la console Rails. Idéal pour les tâches d'administration ponctuelles où cela ne vaut pas la peine de configurer un script ou une migration.

Sur votre machine de production:

script/console production

... puis ...

User.create(:name => "Whoever", :password => "whichever")

Si vous générez cet utilisateur initial plus d'une fois, vous pouvez également ajouter un script dans Rails_ROOT/script/et l'exécuter à partir de la ligne de commande sur votre machine de production, ou via une tâche capistrano.

3
Trevor Stow

Excellent article de blog sur ce sujet: http://railspikes.com/2008/2/1/loading-seed-data

J'utilisais les suggestions de Jay d'un ensemble spécial d'appareils, mais je me suis rapidement retrouvé à créer des données qui ne seraient pas possibles en utilisant directement les modèles (entrées non versionnées lorsque j'utilisais actes_as_versioned)

3
Kevin Davis

Cette tâche Rake peut être fournie par le plugin db-populate:

http://github.com/joshknowles/db-populate/tree/master

3
pantulis

Pour les utilisateurs et les groupes, la question des utilisateurs préexistants doit être définie par rapport aux besoins de l'application plutôt qu'aux aléas de la programmation. Peut-être que votre application nécessite un administrateur; puis préremplissez. Ou peut-être pas - puis ajoutez du code pour demander gracieusement une configuration utilisateur au moment du lancement de l'application.

Sur la question plus générale, il est clair que de nombreuses applications Rails peuvent bénéficier d'une date préremplie. Par exemple, une application détenant une adresse aux États-Unis peut également contenir tous les États et leurs abréviations. Pour ces cas, les migrations sont ton ami, je crois.

2
NickR

Je le garderais dans une migration. Bien qu'il soit recommandé d'utiliser le schéma pour les configurations initiales, la raison en est qu'il est plus rapide, évitant ainsi les problèmes. Une seule migration supplémentaire pour les données devrait convenir.

Vous pouvez également ajouter les données dans le fichier de schéma, car il s'agit du même format que les migrations. Vous perdriez simplement la fonction de génération automatique.

2
MattW.

Certaines réponses sont dépassées. Depuis Rails 2.3.4, il existe une fonctionnalité simple appelée Seed disponible dans db/seed.rb:

#db/seed.rb
User.create( :name => 'default', :password => 'password' )
Comment.create( :title => 'Title', :body => 'First post!' )

Il fournit une nouvelle tâche de râteau que vous pouvez utiliser après vos migrations pour charger des données:

rake db:seed

Seed.rb est un classique Ruby, n'hésitez pas à utiliser n'importe quelle infrastructure de données classique (tableau, hachages, etc.) et des itérateurs pour ajouter vos données:

["bryan", "bill", "tom"].each do |name|
  User.create(:name => name, :password => "password")
end

Si vous souhaitez ajouter des données avec des caractères UTF-8 (très courant en français, espagnol, allemand, etc.), n'oubliez pas d'ajouter au début du fichier:

# Ruby encoding: utf-8

Ce Railscast est une bonne introduction: http://railscasts.com/episodes/179-seed-data

1
frenci