web-dev-qa-db-fra.com

Ajout d'une clé étrangère à un modèle Rails

Je suis assez nouveau pour Rails et j'ai essayé de résoudre ça toute la nuit sans succès.

J'ai créé 3 modèles: users, businesses et business_hours. J'ai également ajouté les associations (business_hours belongs_to businesses which belongs_to users) et (user has_one business which has_many business_hours).

En lisant les documents en ligne, il semble que je dois maintenant créer les clés étrangères pour ces relations dans mes tables de base de données. Comment faire cela en utilisant Rails Migrations ActiveRecord? J'utilise PostgreSQL comme base de données.

37
user470763

Tout d'abord, lorsque vous utilisez la méthode Appartient à, n'utilisez pas s à la fin du mot: business_hours belongs_to business which belongs_to user.

Créez maintenant une migration:

Rails generate migration migration_name

Et dans la migration, ajoutez des colonnes:

class MigrationName < ActiveRecord::Migration
  def change
    add_foreign_key :business_hours, :businesses
    add_foreign_key :businesses, :users
  end
end

Courir rake db:migrate. C'est ça.

29
Danil Speransky

La réponse actuellement acceptée à ce sujet n'est pas vraiment exacte car elle n'ajoute pas de clé étrangère de base de données. Il s'agit simplement d'ajouter des colonnes entières.

Dans Rails 4.2.x , l'approche actuelle est la suivante:

http://guides.rubyonrails.org/active_record_migrations.html#foreign-keys

Créez une migration:

Rails generate migration migration_name

Pour les colonnes existantes , dans la migration, ajoutez les clés étrangères comme ceci:

class MigrationName < ActiveRecord::Migration
  def change
    add_foreign_key :business_hours, :businesses
    add_foreign_key :businesses, :users
  end
end

Pour Rails 4.x ou si vous ajoutez une nouvelle colonne et que ce soit une clé étrangère, vous pouvez le faire, où vous voudrez probablement aussi spécifier l'index comme vrai, mais cela ne fait pas partie de l'exigence pour la clé étrangère:

http://edgeguides.rubyonrails.org/active_record_migrations.html#creating-a-migration

class MigrationName < ActiveRecord::Migration
  def change
    add_reference :business_hours, :business, index: true, foreign_key: true
    add_reference :businesses, :user, index: true, foreign_key: true
  end
end
59
Chris

Je ne l'ai pas essayé avec PostgreSQL mais au moins avec MySQL Rails NE PAS créer de clés étrangères, je veux dire pas de vraies clés étrangères de niveau db. Tout ce qu'elles créent est un entier qui est nommé d'après Cela signifie que hors de la boîte, vous n'obtenez pas l'index sur cette fausse clé étrangère (pour une recherche plus rapide) et il n'y a pas non plus de vérification d'intégrité référentielle au niveau db. Pour obtenir cela, vous devez faire quelque chose comme:

ALTER TABLE your_table ADD CONSTRAINT fk_whatever_you_want_to_name_it FOREIGN KEY   (foreign_key_name) REFERENCES another_table(its_primary_key)

Dans une migration Rails vous pouvez passer ceci comme un argument de chaîne à la fonction "exécuter". L'ajout d'une "vraie" clé étrangère crée également automatiquement un index. Au moins pour moi, c'était plutôt désagréable surprise.

6
Renra

Rails 5 peut désormais ajouter une clé étrangère dans les migrations, voir http://devdocs.io/Rails~5.0/activerecord/connectionadapters/schemastatements#method-i-add_foreign_key . Alors

 add_foreign_key :articles, :authors

crée

 ALTER TABLE "articles" ADD CONSTRAINT fk_Rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")

Si vous avez un modèle de données non standard, vous pouvez le faire.

 add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"

ce qui crée

 ALTER TABLE "articles" ADD CONSTRAINT fk_Rails_58ca3d3a82 FOREIGN KEY ("author_id") REFERENCES "users" ("lng_id")
5
Ben Edwards