Rails migration: t.references with alternative name?
Solution 1
I think this thread has a different more Rails-ish way: Scaffolding ActiveRecord: two columns of the same data type
In the migration:
t.belongs_to :transferrable_as
t.belongs_to :same_as
Solution 2
You can do this all in the initial migration/column definition (at least currently in Rails 5):
t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}
Solution 3
You can do it this way:
create_table :courses do |t|
t.string :name
t.references :transferrable_as
t.references :same_as
t.timestamps
end
or using t.belongs_to
as an alias for t.references
You can't add foreign_key: true
to those two references lines. If you want to mark them as foreign keys at the database level you need to have a migration with this:
add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id
Update
In Rails 5.1 and above you can add the foreign key in the migration in the create_table
block like this:
create_table :courses do |t|
t.string :name
t.references :transferrable_as, foreign_key: { to_table: 'courses' }
t.references :same_as, foreign_key: { to_table: 'courses' }
t.timestamps
end
Solution 4
As an added answer to this question -- the Model should have the following line to complete the association:
belongs_to :transferrable_as, class_name: "Course"
belongs_to :same_as, class_name: "Course"
Solution 5
I don't think references
accepts the :as
option, but you can create your columns manually...
create_table :courses do |t|
t.string :name
t.integer :course1_id
t.integer :course2_id
t.timestamps
end
themirror
Updated on July 08, 2022Comments
-
themirror almost 2 years
So I have a create_table like this for Courses at a School:
create_table :courses do |t| t.string :name t.references :course t.timestamps end
but I want it to reference two other courses like:
has_many :transferrable_as # A Course has_many :same_as # Another Course
Can I say the following?
t.references :transferrable_as, :as=> :course
-
Toby 1 Kenobi almost 9 yearsbut how does the db know which foreign key to link the table to? I'm trying this with Postgres database and it's giving me an error
PG::UndefinedTable: ERROR
it's trying to add a foreign key constraint to a table that doesn't exist. -
Matthew Clark almost 9 yearsThe part about not being able to add
foreign_key: true
to the references lines was what was tripping me up. Adding theadd_foreign_key
and specifying the column name for those did the trick. -
Beni Cherniavsky-Paskin about 8 yearsDoes this work out of the box in Rails? According to stackoverflow.com/a/22384289/239657, this requires the
schema_plus
gem. Rails' add_reference docs don't mention a :references options. -
Toby 1 Kenobi about 8 yearsIt works out of the box on Rails 4.2 in my experience. Interesting observation about that option nor being in the docs. Those docs also say that the :foreign_key option is available but I found it wasn't. Perhaps a different method gets called somehow.
-
MCB over 7 yearsI'm not following what the
references:
option is for (as opposed tot.references
wouldn't that only be relevant on the model level, with the foreign_key considerations being taken care of byadd_foreign_key
? -
Toby 1 Kenobi over 7 years@MCB
t.references
says "add a field to this table that is the primary key of another table." Thereferences:
option tells it which table it is a primary key of (needed if it is not clear by the name of the field). Theadd_foreign_key
function tells the database to enforced referential integrity here. -
MCB over 7 years@Toby1Kenobi Ok, I ran them both and didn't notice any difference in my schema though
-
Toby 1 Kenobi over 7 years@MCB you ran both what exactly?
-
MCB over 7 years@Toby1Kenobi Oh, a migration each way, with a
references: :user
and I rolled it back and ran it again without that, and the schema looked the same both ways. -
Toby 1 Kenobi over 7 years@MCB what did you name the attribute?
-
MCB over 7 years@Toby1Kenobi the line was
t.belongs_to :vendor
and a vendor is a user -
Toby 1 Kenobi over 7 years@MCB oh, well I suppose ActiveRecord doesn't need to know what table it's referencing to make a foreign key, if all primary keys are the same type (integer), but it makes me feel better if it does have access to that info. What if in the future it supports a database back end where the primary key can be a variety of different types? Then the
references:
option would be needed. -
MCB over 7 yearsNo idea, never handled that situation before, and honestly only have really dealt with a db through AR except when issues were dire. But as far as I know this is all handled at the model level and migrations just handle setting up the DB. Would postgresql ever need this info or just for writing sql?
-
stephenmurdoch about 7 yearsThis works on Rails 5.1 and none of the other suggestions do. It's much cleaner, and feels right.
-
Quv over 6 yearsI use Rails 5.1.4 but it doesn't work. When I specify a
foreign_key
option in the table creation like this ways, it raises an error saying the very table I'm creating doesn't exist... So I suspect it's not really supported by the official API. -
Jonathan Reyes about 6 yearsI also read that
index
is already added to foreign keys as of Rails stackoverflow.com/questions/39769981/… -
Toby 1 Kenobi almost 6 years@MCB after all this time I realise you were right all along. Your first comment above is exactly right - the
add_foreign_key
lines take care of informing the database what is a foreign key of what. Thereferences:
parameter is doing nothing. -
Jason Swett over 5 yearsIn case anyone is wondering,
belongs_to
is just an alias toreferences
and so has the exact same functionality. -
Serge Vinogradov about 3 yearsfrom what I've seen, passing
index:true
is redundant,t.references :transferable_as, foreign_key: {to_table: :courses}
also creates index.