简体   繁体   中英

Adding foreign key to a rails model

I'm quite new to rails and have been trying to work this out all night with no luck.

I have created 3 models: users , businesses , and business_hours . I have also added the associations ( business_hours belongs_to businesses which belongs_to users ) and ( user has_one business which has_many business_hours ).

Reading through the docs online it seems I now need to create the foreign keys for these relationships in my DB tables. How do I do this using Rails ActiveRecord migrations? I'm using PostgreSQL as my DB.

The currently accepted answer on this isn't really accurate as it doesn't add a database foreign key. It's just adding integer columns.

In Rails 4.2.x , the current approach is:

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

Create a migration:

rails generate migration migration_name

For existing columns , in the migration add the foreign keys like this:

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

For Rails 4.x or if you're adding a new column and want it to be a foreign key you can do this, where you probably also want to specify the index as true, but that's not part of the requirement for the foreign key:

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

First of all when you use belongs_to method don't use s at the end of the word: business_hours belongs_to business which belongs_to user .

Now create a migration:

rails generate migration migration_name

And in migration add columns:

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

Run rake db:migrate . That's it.

I haven't tried it with PostgreSQL but at least with MySQL Rails do NOT create foreign keys, I mean not real db-level foreign keys. All they create is an integer that is named according to the convention. That means that out of the box you do not get the index on this fake foreign key(for faster lookup) and there is also no db-level referential integrity check. To get that you need to do something like:

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

In a Rails migration you can pass this as a string argument to the "execute" function. Adding a "real" foreign key also automatically creates an index. At least for me this was a rather nasty surprise.

Rails 5 now can add foreign key in migrations, see http://devdocs.io/rails~5.0/activerecord/connectionadapters/schemastatements#method-i-add_foreign_key . So

 add_foreign_key :articles, :authors

creates

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

If you have a non standard data model you can do.

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

which creates

 ALTER TABLE "articles" ADD CONSTRAINT fk_rails_58ca3d3a82 FOREIGN KEY ("author_id") REFERENCES "users" ("lng_id")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM