In my example a User knows about many Words and each Word is known by many Users.
You can find many pages on the web about the differences. The consensus is that has_many :through is the way to go from the start - and after this process I agree.
Making the change in itself is not a big deal - drop the existing joining table 'users_words', create the new one, update the User and Word models and you're good to go.
Problem is that I already had data in the joining table...
And because the standard way of setting up a HABTM joining table does not include an id column, you can't just use that table or directly copy each record from it. Dang it...
Here were my steps - hopefully I got them all - don't skip any !
1: Backup your database and prevent users from accessing it
2: Do not touch any of the old associations, table, etc
3: Create the new table and model with a different name from the old joining table.
My HABTM table was users_words and my new table is user_work_links
4: Update the two models
My original association was this - do not change it yet !
has_and_belongs_to_many :words, :uniq => true
The new association is this - NOTE the second line is commented out for now - VERY important !
has_many :user_word_links, :dependent => :destroy
# has_many :words, :through => :user_word_links, :uniq => true
5: Copy over the data from the old joining table with a rake task
You need to go through the existing associations one by one to get the ids for records in the two tables.
Here is my script:
namespace :craic do
desc "move user word data"
task :move_user_word_data => :environment do
users = User.all
users.each do |user|
user.words.each do |word|
record = UserWordLink.new({ :user_id => user.id, :word_id => word.id })
record.save
end
end
end
end
6: Update the two models
Now you can comment out the old associations and uncomment the new ones
# has_and_belongs_to_many :words, :uniq => true
has_many :user_word_links, :dependent => :destroy
has_many :words, :through => :user_word_links, :uniq => true
In the attr_accessible lists in the two models be sure to add :user_ids in the Word model and :word_ids in the User model. If your forget this it will silently fail to create the records
7: Test Test Test
You should be back up and running with the new model
8: Remove the old table
Finally create a migration that drops the old table and run it
Not too bad as long as you think it through before you start and don't rush the steps
Very significant article for us , I think the representation of this article is actually superbly one. This is my first visit to your site.
ReplyDeleteAdvertising agencies in Karachi
This comment has been removed by the author.
ReplyDelete