Reputation: 48011
I'm just starting to learn Rails migrations. I have a table called tags
with a column name
[string] (and with the auto-generated id
column). I want to migrate it so that the table uses the name
column as the id
and primary key. How do I do this making sure all existing records work with the new schema?
Upvotes: 1
Views: 2034
Reputation:
The approach is straightforward, but the execution seems risky. getting the migration up working is fairly straight forward, but the down? not sure.
If you find that the column is not unique you'll have to come up with some kind of plan to change that...like name+id in the name field for duplicates or something similar. All of this can be done from a migration, of course.
I suggest leaving the id column there but only use it to resolve issues you find along the way
By way of example, assume this is your model around the tags table:
class Tag < ActiveRecord::Base
end
Assume you have at least this other model, Thing, that has a simple association with the Tag model:
class Thing < ActiveRecord::Base
has_one :tag
end
There is a tag_id column on the things table. I'd add a column called tag_name, change the association to have a foreign key pointing to this new column...
class Thing < ActiveRecord::Base
has_one :tag, :foreign_key => "tag_name"
end
This tells Rails that the association between these things is through the new column. By convention it would look for "tag_id".
Given this change you can go into the migration and:
add_column :things, :tag_name, :string
Thing.all.each do |thing|
if thing.tag
thing.tag_name = thing.tag.name
end
end
remove_column :things, :tag_id
This is a quick and dirty example and I might have missed something. the key thing is to add the new column, move the association, remove the old column.
There are other scenarios like the case where the model is involved in a many to many association or some polymorphic association, but the general approach would be similar in those cases.
Upvotes: 3