Add_Foreign_Key VS Add_Reference in Rails

Add a reference column migration in Rails 4

Rails 4.x

When you already have users and uploads tables and wish to add a new relationship between them.

All you need to do is: just generate a migration using the following command:

rails g migration AddUserToUploads user:references

Which will create a migration file as:

class AddUserToUploads < ActiveRecord::Migration
def change
add_reference :uploads, :user, index: true
end
end

Then, run the migration using rake db:migrate.
This migration will take care of adding a new column named user_id to uploads table (referencing id column in users table), PLUS it will also add an index on the new column.

UPDATE [For Rails 4.2]

Rails can’t be trusted to maintain referential integrity; relational databases come to our rescue here. What that means is that we can add foreign key constraints at the database level itself and ensure that database would reject any operation that violates this set referential integrity. As @infoget commented, Rails 4.2 ships with native support for foreign keys(referential integrity). It's not required but you might want to add foreign key(as it's very useful) to the reference that we created above.

To add foreign key to an existing reference, create a new migration to add a foreign key:

class AddForeignKeyToUploads < ActiveRecord::Migration
def change
add_foreign_key :uploads, :users
end
end

To create a completely brand new reference with a foreign key(in Rails 4.2), generate a migration using the following command:

rails g migration AddUserToUploads user:references

which will create a migration file as:

class AddUserToUploads < ActiveRecord::Migration
def change
add_reference :uploads, :user, index: true
add_foreign_key :uploads, :users
end
end

This will add a new foreign key to the user_id column of the uploads table. The key references the id column in users table.

NOTE: This is in addition to adding a reference so you still need to create a reference first then foreign key (you can choose to create a foreign key in the same migration or a separate migration file). Active Record only supports single column foreign keys and currently only mysql, mysql2 and PostgreSQL adapters are supported. Don't try this with other adapters like sqlite3, etc. Refer to Rails Guides: Foreign Keys for your reference.

Add a reference column migration in Rails 5

As with prior versions of Rails, you may use the following command to create the migration:

rails g migration AddUserToUploads user:references

Unlike prior versions of Rails, the migration looks like:

class AddUserToUploads < ActiveRecord::Migration[5.0]
def change
add_reference :uploads, :user, foreign_key: true
end
end

Difference between add_references and add_column in rails

TLDR

#add_column is meant for adding a column like the name suggests.

#add_reference is meant as a shortcut for creating a column, index and foreign key at the same time.

Explanation

In your example the only difference is the index on the column that will be created by #add_reference that defaults to true.

add_reference :books, :author
# equals
add_column :books, :author_id, :integer
add_index :books, :author_id

But if you would take the following line:

add_reference :books, :author, foreign_key: true

It would also create a foreign key constraint.

Furthermore if you would like to have every author be able to publish only one book you can set the unique constraint through #add_reference by doing the following:

add_reference :books, :author, null: false, index: {unique: true}, foreign_key: true

This requires every book to have an author and restraints the authors to have a maximum of one book.

The same can be done using #add_column by doing the following:

add_column :books, :author_id, :integer, null: false
add_index :books, :author_id, unique: true
add_foreign_key :books, :authors

No relationship between tables shown in schema diagram when using add_reference in Rails

The fact is that add_reference does not add a foreign key by default. The API Docs for v5.2 or v5.0 state that the options hash can include a :foreign_key key to set the appropriate foreign key constraint.

So, to use add_reference just change your code to include foreign_key: true as an option.

add_reference :parts, :user, foreign_key: true

Generate model in Rails using user_id:integer vs user:references

Both will generate the same columns when you run the migration. In rails console, you can see that this is the case:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

The second command adds a belongs_to :user relationship in your Micropost model whereas the first does not. When this relationship is specified, ActiveRecord will assume that the foreign key is kept in the user_id column and it will use a model named User to instantiate the specific user.

The second command also adds an index on the new user_id column.

Add reference in my migration error

You don't have a styles table.

How to add reference to a non primary key column of a table in rails5

Try primary_key:

class Transaction < ApplicationRecord
belongs_to :from_account, :foreign_key => 'from_account', :class_name => 'Account', :primary_key => 'account_number'
belongs_to :to_account, :foreign_key => 'to_account', :class_name => 'Account', :primary_key => 'account_number'
end


Related Topics



Leave a reply



Submit