class AddTagDisplayName < ActiveRecord::Migration class Tag < ActiveRecord::Base has_and_belongs_to_many :articles end class Content < ActiveRecord::Base end class Article < Content has_and_belongs_to_many :tags end def self.up STDERR.puts 'Adding display name to tags' modify_tables_and_update(:add_column, Tag, :display_name, :string) do unless $schema_generator Tag.find(:all).each do |tag| tag.display_name = tag.name tag.name = tag.name.tr(' ', '').downcase if tag.name != tag.display_name # we need to make sure we're not attempting to create duplicate-named tags # if so, we need to coalesce them # Hopefully this code isn't necessary, but somebody may have tags "Monty Python" and "montypython" # Please note that this code isn't going to be tested very well, if at all, because of my limited # testing setup. But in my quickie tests it appears to be working right if origtag = Tag.find(:first, :conditions => [%{name = ? AND id != ?}, tag.name, tag.id]) tag.articles.each do |article| # replace our tag with origtag in article.tags article.tags = article.tags.collect { |x| x.id == tag.id ? origtag : x } end tag.destroy else # ok, original tag tag.save! end else tag.save! end end end end end def self.down STDERR.puts 'Removing display name from tags' unless $schema_generator Tag.find_and_update(:all) do |tag| tag.name = tag.display_name end end remove_column :tags, :display_name end end