2008-09-23 5 views
2

Je voudrais confirmer que l'analyse suivante est correcte:Utilisation des migrations dans Ruby on Rails

Je crée une application Web dans RoR. J'ai une structure de données pour mes postgres db conçues (environ 70 tables, cette conception peut avoir besoin de modifications et d'ajouts pendant le développement pour refléter les façons de faire de Rails.) EG, j'ai conçu des tables d'utilisateurs et de rôles. Authentification, je vais les frotter et les remplacer avec tout ce que RA nécessite.). J'ai un shellscript qui appelle une série de fichiers .sql pour remplir la base de données vide avec des tables et des données initiales (par exemple, les villes sont pré-remplies de villes postales) ainsi que des données de test (par exemple, les entreprises obtient quelques entreprises factices donc j'ai des données à jouer avec).

par exemple:

CREATE TABLE towns (
    id   integer PRIMARY KEY DEFAULT nextval ('towns_seq'), 
    county_id integer REFERENCES counties ON DELETE RESTRICT ON UPDATE CASCADE, 
    country_id integer REFERENCES countries ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL, 
    name  text NOT NULL UNIQUE 
); 

Proposition 0: Les données dure plus longtemps que les applications, donc je suis convaincu que je veux l'intégrité référentielle appliquée au niveau de la DB, ainsi que des validations dans mes modèles RoR, malgré l'absence de SÉCHERESSE. Proposition 1: Si je remplace les fichiers script et sql par Migrations, il est actuellement impossible de dire à ma base de données Postgres à propos de la clé étrangère et d'autres contraintes actuellement définies dans les fichiers DDL SQL dans le code de migration.

Proposition 2: L'avantage des migrations est que les modifications du schéma sont versionnées avec le code du modèle RoR. Mais si je garde mes scripts et mes fichiers .sql dans railsapp/db, je peux les éditer aussi facilement.

Proposition 3: Étant donné que les migrations manquent de fonctionnalités et que je peux offrir des avantages que je peux reproduire, il y a peu de raisons pour que je considère leur utilisation. Donc, je devrais --skipmigrations au script/générer le temps du modèle.

Ma question: Si la proposition 0 est acceptée, les propositions 1,2,3 sont-elles vraies ou fausses, et pourquoi?

Merci!

+0

Mise en forme du code: utilisez 4 espaces avant chaque ligne de code. StackOverflow le traitera comme un bloc pré-formaté (y compris l'indentation) et la plupart du temps sélectionnera la syntaxe qui lui convient le mieux. – webmat

+0

Voilà, @webmat. –

+0

choses à considérer lors de l'implémentation de la conception de base de données https://cbabhusal.wordpress.com/2015/08/16/ruby-on-rails-order-of-migration-generator-matters-in-initial-design/ – illusionist

Répondre

10

La proposition 1 est fausse dans au moins deux situations - vous pouvez utiliser des plugins comme foreign_key_migrations pour faire le suivant:

def self.up 
    create_table :users do |t| 
    t.column :department_id, :integer, :references => :departments 
    end 
end 

qui crée la contrainte de clé étrangère appropriée dans votre base de données.

Bien sûr, vous pourriez avoir d'autres choses que vous voulez faire dans votre DDL, auquel cas la deuxième situation devient plus convaincante: vous n'êtes pas obligé d'utiliser le Ruby DSL dans les migrations.Essayez la méthode execute, à la place:

def self.up 
    execute 'YOUR SQL HERE' 
end 

Avec cela, vous pouvez garder le contenu de vos scripts SQL dans les migrations, gagnant les avantages de ce dernier (le plus en évidence les down méthodes, que vous n'avez pas abordé dans votre question originale) et en conservant le contrôle de niveau inférieur que vous préférez.

+0

Merci! Je n'avais pas vu le plugin de migration de clé étrangère. Et exécuter est le meilleur des deux mondes. Ainsi, les migrations deviennent utiles (ce qui est mieux, car cela ressemble plus à la façon Rails.) – NickR

4

La proposition 1 est erronée: vous pouvez définir définitivement l'intégrité référentielle en utilisant des migrations si seulement en utilisant le SQL direct dans la migration, voir this post pour plus de détails.

Proposition 2: L'intérêt vanté des migrations est de pouvoir définir votre modèle de base de données de façon incrémentielle tout en gardant une trace de ce que chaque changement ajouté et être capable de facilement annuler un tel changement à un moment ultérieur.

Vous devez faire attention à l'ordre dans lequel vous créez/modifiez les choses, mais vous pouvez le faire. Une chose à garder à l'esprit: les rails sont mieux adaptés à la conception centrée sur l'application. dans la Rails Way (tm) la base de données n'est accessible que via la couche d'enregistrement active de l'application et expose les données à l'extérieur en utilisant les services web

+0

Merci! Je suis d'accord avec vous sur Rails Way. Mais mon application a démarré il y a longtemps dans FileMaker Pro (croiriez-vous). Il a été webified en utilisant Tomcat, Velocity et Turbine en même temps. Sans doute dans cinq ans je voudrai l'implémenter sur un Holodeck en utilisant ZiML. Mais les données seront toujours là ... – NickR

+0

pas de problème :) comme ben scofield et moi l'avons souligné, vous pouvez toujours utiliser les migrations pour la définition des contraintes. vous pouvez également exporter le schéma vers sql si vous avez besoin de vous éloigner des rails – Jean

1

1: Vous pouvez essayer this plugin. Je ne l'ai pas essayé moi-même, mais il semble être capable d'ajouter des contraintes de clés étrangères à travers les migrations. 2: Le véritable avantage de la migration est la capacité à aller et venir dans l'historique de votre base de données. Ce n'est pas aussi facile avec vos fichiers .sql. 3: Voyez si le plugin mentionné ci-dessus fonctionne pour vous, puis décidez :) En tout cas, ce n'est pas un péché capital si vous ne les utilisez pas!

+0

Merci. Et oui, la permission de ne pas suivre le Rails Waytm est très importante :-) – NickR

0

Comme vous utilisez Postgres et que vous ne voulez pas installer le plugin foreign_key_migrations, voici ce que je fais lorsque je veux utiliser à la fois les migrations et les contraintes de clés étrangères.

J'ajoute une méthode SchemaStatements à ActiveRecord :: SchemaStatements appelée "add_fk_constraint". Cela pourrait aller dans un fichier centralisé, mais dans l'exemple de fichier de migration ci-dessous, je viens de le mettre en ligne.


module ActiveRecord 
    module ConnectionAdapters # :nodoc: 
    module SchemaStatements 
     # Example call: 
     # add_fk_constraint 'orders','advertiser_id','advertisers','id' 
     # "If you want add/alter a 'orders' record, then its 'advertiser_id' had 
     # better point to an existing 'advertisers' record with corresponsding 'id'" 
     def add_fk_constraint(table_name, referencing_col, referenced_table, referenced_col) 
     fk_name = "#{table_name}_#{referencing_col}" 
     sql = <<-ENDSQL 
      ALTER TABLE #{table_name} 
      ADD CONSTRAINT #{fk_name} 
      FOREIGN KEY (#{referencing_col}) REFERENCES #{referenced_table} (#{referenced_col}) 
      ON UPDATE NO ACTION ON DELETE CASCADE; 
      CREATE INDEX fki_#{fk_name} ON #{table_name}(#{referencing_col}); 
     ENDSQL 
     execute sql 
     end 
    end 
    end 
end 

class AdvertisersOrders < ActiveRecord::Migration 
    def self.up 
    create_table :advertisers do |t| 
     t.column :name,    :string, :null => false 
     t.column :net_id,    :integer, :null => false 
     t.column :source_service_id, :integer, :null => false, :default => 1 
     t.column :source_id,   :integer, :null => false 
    end 

    create_table :orders do |t| 
     t.column :name,    :string, :null => false 
     t.column :advertiser_id,  :integer, :null => false 
     t.column :source_id,   :integer, :null => false 
    end 
    add_fk_constraint 'orders','advertiser_id','advertisers','id' 
    end 

    def self.down 
    drop_table :orders 
    drop_table :advertisers 
    end 
end 

J'espère que cela aide quelqu'un. Cela m'a été très utile car j'ai besoin de charger beaucoup de données externes avec des appels SQL "COPY", mais je trouve le système de migration très pratique.