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
Example of a Prepared Insert Statement Using Ruby Pg Gem
How to Make a Check Box Default to Being "Checked" in Rails 1.2.3
Is There a Ruby One-Line "Return If X"
Programmatically Getting Full Ruby Version
Describe VS Context in Rspec. Differences
Setting Up Env, Osx Rbenv and Bundle Battle
How to Make a Before_Save Conditional
How to Test Instance Variable Was Instantiated in Controller with Rspec
How to Integrate Rubocop with Rake
How to Get List of All Countries and Cities in Rails
Differencebetween 'File.Read' and 'Io.Read'
How to Remove a Non-Breaking Space in Ruby
Paperclip: Upload from Url with Extension