Specifying column name in a "references" migration

Ruby on-RailsRuby on-Rails-3ActiverecordRails Migrations

Ruby on-Rails Problem Overview


I want to make a migration in Rails, referencing another table. Usually, I would do something like:

add_column :post, :user, :references

This creates a column named user_id in posts table. But what if, instead of user_id, I want something like author_id? How can I do that?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

For Rails 5+

Initial Definition:

If you are defining your Post model table, you can set references, index and foreign_key in one line:

t.references :author, index: true, foreign_key: { to_table: :users }

Update Existing:

If you are adding references to an existing table, you can do this:

add_reference :posts, :author, foreign_key: { to_table: :users }

Note: The default value for index is true.

Solution 2 - Ruby on-Rails

In Rails 4.2+ you can also set foreign keys in the db as well, which is a great idea.

For simple associations this can be done also on t.references adding foreign_key: true, but in this case you'll need two lines.

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

Solution 3 - Ruby on-Rails

In rails 4, when using postgresql and the schema_plus gem you can just write

add_reference :posts, :author, references: :users

This will create a column author_id, which correctly refers to users(id).

And in your model, you write

belongs_to :author, class_name: "User"

Note, when creating a new table you can write it as follows:

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

> Note: the schema_plus gem in it's entirety is not compatible with rails 5+, but this functionality is offered by the gem schema_auto_foreign_keys (part of schema_plus) which is compatible with rails 5.

Solution 4 - Ruby on-Rails

Do it manually:

add_column :post, :author_id, :integer

but now, when you create the belongs_to statement, you will have to modify it, so now you have to call

def post
    belongs_to :user, :foreign_key => 'author_id'
end

Solution 5 - Ruby on-Rails

If you aren't using a foreign key, then it doesn't matter what the actual table name of the other table is.

add_reference :posts, :author

As of Rails 5, if you're using a foreign key, you can specify the name of the other table in the foreign key options. (see https://github.com/rails/rails/issues/21563 for discussion)

add_reference :posts, :author, foreign_key: {to_table: :users}

Prior to Rails 5, you should add the foreign key as a separate step:

add_foreign_key :posts, :users, column: :author_id

Solution 6 - Ruby on-Rails

alias_attribute(new_name, old_name) is very handy. Just create your model and the relationship:

rails g model Post title user:references

then edit the model and add an attribute alias with

alias_attribute :author, :user

After that you'll be able to run things like

Post.new(title: 'My beautiful story', author: User.first)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncaarlos0View Question on Stackoverflow
Solution 1 - Ruby on-RailsSheharyarView Answer on Stackoverflow
Solution 2 - Ruby on-RailsecoologicView Answer on Stackoverflow
Solution 3 - Ruby on-RailsnathanvdaView Answer on Stackoverflow
Solution 4 - Ruby on-RailsmschultzView Answer on Stackoverflow
Solution 5 - Ruby on-Railsjes5199View Answer on Stackoverflow
Solution 6 - Ruby on-RailssekmoView Answer on Stackoverflow