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
2 comments:
Very significant article for us , I think the representation of this article is actually superbly one. This is my first visit to your site.
Advertising agencies in Karachi
Post a Comment