Err the Blog Atom Feed Icon
Err the Blog
Rubyisms and Railities
  • “Sexy Migrations”
    – Chris on March 29, 2007

    Damn, that new release of Hobo reminds me: those guys have got some nice looking migrations. Let’s take it a step further. Let’s bring sexy back.

    Let’s turn this:

    class UpdateYourFamily < ActiveRecord::Migration
      create_table :updates do |t|
        t.column :user_id,  :integer
        t.column :group_id, :integer
        t.column :body,     :text
        t.column :type,     :string
    
        t.column :created_at, :datetime
        t.column :updated_at, :datetime
      end
    
      def self.down
        drop_table :updates
      end
    end
    

    Into this:

    class UpdateYourFamily < ActiveRecord::Migration
      create_table :updates do
        foreign_key :user
        foreign_key :group
    
        text   :body
        string :type
    
        timestamps!
      end
    
      def self.down
        drop_table :updates
      end
    end
    

    Using this:

    SVN:
    $ ./script/plugin install \ svn://errtheblog.com/svn/plugins/sexy_migrations

    Piston:
    $ piston import svn://errtheblog.com/svn/plugins/sexy_migrations \ vendor/plugins/sexy_migrations

    That’s it. It works with them newfangled Independent Migrations and is 100% backwards compatible. Keep your old migrations, sex up your new migrations. But, be careful: it’s real hard to go back to the ‘old way’ of writing migrations once you start getting your sexy on. You’ve been warned.

    Bugs!

    You heard that Lighthouse launched, right? Right. From now on, any bugs found in any Err plugins should be reported at the Err plugins Lighthouse project. You can jump straight to creating a new ticket if you’d like. (Just make sure to include the name of the plugin you’re reporting a bug for.)

    Oh, and speaking of bugs: you may want to follow Err on Twitter. We’ll be using it to post updates about our projects and plugins and blogs, oh my. Oh yeah.

  • rubylicio.us, about 4 hours later:

    very sexy indeed.

  • Ted, about 7 hours later:

    Does the foreign_key create actual referential integrity like http://www.redhillonrails.org/#foreign_key_migrations ?

  • Gustav Paul, about 7 hours later:

    sweet :) Well done man.

  • Josh Schairbaum, about 7 hours later:

    I really like the syntax of this, but wanted to make you aware of a recent patch that has a similar syntax, but relies on a method_missing hack, of sorts. The patch isn’t nearly as complete as this, but thought I’d pass it along.

  • Chris, about 9 hours later:

    Ted: This doesn’t create actual foreign key constraints, but I don’t see why this plugin couldn’t work in harmony in the redhillonrails one.

  • Tom Locke, about 10 hours later:

    Damn you err-the-blog man! I was going to add that to Hobo. You’ve totally stolen my thunder ;o)

    One query – what’s special about ‘timestamps!’ that it should have a bang on the end?

  • Chris, about 10 hours later:

    Tom: Nothing too special. It’s aliased as timestamps, auto_dates, and auto_dates!—you can use whichever you’d like. I like the bang because it does two things at once, things you can do yourself, so it reminds me that it’s ssssspecial.

  • Ryan Bates, about 15 hours later:

    That is very cool. Will have to try it out.

    Oh yeah, where’s the “self.up” method definition? Was it left off by accident?

  • Joe Van Dyk, about 15 hours later:

    The svn repository is asking me for a password…

  • Sam Livingston-Gray, 1 day later:

    I’ll be in my bunk.

  • Dan Kubb, 1 day later:

    My greatest wish for migrations would be for me to specify what I normally add for the “self.up” method, and for the “self.down” method to be automatically generated.

    If it were coded to understand what the reversal method was for each add/create method, and actions were run in reverse order to how they were defined, I think alot of it could be automated.

    Of course there are some things that cannot be reversed, which is where an exception needs to be thrown, but I still think most of what we do in migrations could be DRYed up.

  • Sam Livingston-Gray, 1 day later:

    @Dan Kubb: the TextMate Rails bundle includes a macro that understands how to reverse many of the basic migration steps, and fills in the corresponding self.down line as you type the self.up line. If you’re on Windows, e-texteditor.com may support this.

    Point being, you might need to write this yourself. With TextMate so popular in the Rails world, I doubt the core team is particularly feeling your pain.

  • Chris, 1 day later:

    Dan: I hear ya—I usually do something like this in my initial migration.

  • Phil, 1 day later:

    While this looks really cool, I don’t know that I could give up all of the handy TextMate snippets that I use when creating migrations. Hmmm…maybe I will need to create some new TextMate snippets :-)

  • Prince, 1 day later:

    I’m not sure why you are talking about bringing sexy back.

    Sexy never left.

  • ylon, 1 day later:

    Well guys, if you check out some of the chatter going on over here:

    http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week6

    You’ll see that a real ERD model tied into migrations so that a graphical back and forth flow would be much sexier than any textual migration… ;)

  • Antonio, 1 day later:

    It bears mentioning that the down-generating functionality is also present in vim’s Rails package. But then I suppose at the end of the day it’s less about the fact that our editors can reduce the pain (the Java folks can say that, too), and more about not needing the editors to help us repeat ourselves to begin with. Admittedly, migrations are a one-time thing, but still…

    Purely thinking aloud, it’d be nice if, when Rails went to reverse a migration, it checked for a `down’ method. If present, it assumes that the entire reverse migration is in there. If not present, then it changes the meaning of the various potential `up’ methods (e.g., create_table and the add_column, etc, calls) to mean the opposite of what they mean (through some aliasing magic and other voodoo, for example). Now, problems obviously come up with remove_column calls, for example, since the type information isn’t provided when you remove a column. Still, assuming all of the database stuff is in a migration somewhere, you could try doing a scan of the migrations to find where that column is defined, for example.

    This is all a lot of extra work, of course, but it would certainly be nice.

  • Dan Kubb, 3 days later:

    Most of my migrations have down methods that look like mirror images of the up method.

    I think for something like this to work you’d specify whatever you normally do in the up method, and behind the scenes it would generate the up method automatically, and reverse (ordering AND method calls) everything for the down method.

    As Antonio mentioned the main sticking point would be if in your “up” method you wanted to remove a column, you’d need a way to specify enough information so the down method could create the column when reversing the migration.

    Actually what would be nice is if the remove methods took the same arguments as the add/create type methods, and the system made it so you couldn’t remove something unless the arguments provided would allow a exact restoration of whatever you were removing. I hope that made sense. In a way it would sort of be like saying: “remove this column, but only if the column has these precise attributes”.

  • Xin, 4 days later:

    This plugin looks great.

    But, does it sexify update migrations?

    i.e. add_column :groups, :lat, :float

  • Jim Morris, 16 days later:

    Nice! I added a small patch that allows an option of :ref => :reftablename to the foreign_key, this will create a foreign key constraint for that column to the named table, which works for both postgresql and mysql, If you would like the patch let me know where to send it.

    Thanks

  • Chris, 17 days later:

    Jim: Bugs to Lighthouse please.

  • Jim Morris, 17 days later:

    Ok I’ll try, unfortunately Lighthouse doesn’t work with a Firefox browser, so I’ll have to find ie somewhere I guess (hard as I use Linux!)

  • Jim Morris, 17 days later:

    I have filed a patch to lighthouse which also adds indexes.

    eg string :alias, :idx => {:unique => true} # creates a unique index on alias

    integer :user, :idx => true # creates a simple index on user
    foreign_key :user, :ref => :users, :idx => true # creates a foreign key constraint, and an index on user_id
  • topfunky, 20 days later:

    I’m using it right now and feel much sexier.

    Do you think there is any value in abstracting other elements?

    For example,

    inheritable!

    would produce

    t.column :type, :string
  • Chris, 20 days later:

    topfunky: Yep, funny enough I added a polymorphic method before you made your comment. inheritable is now in there. Check my tweet.

  • ylon, about 1 month later:

    Have your “Sexy Migrations” been integrated into Hobo or have you discussed it with Tom Locke? Seems like this might be a nice integration.

  • cies breijs, about 1 month later:

    here the patch for mail line rails: http://dev.rubyonrails.org/changeset/6667

  • Andrew Kuklewicz, about 1 month later:

    So the 6667 changes are nice – but no indices and no foreign keys get created. So I modifed the sexy migrations to have both:

    http://err.lighthouseapp.com/projects/466-plugins/tickets/5-add-indexes-to-sexy_migrations#ticket-5-5

    http://pastie.caboo.se/63388

    Cheers, Andrew

  • Martin, about 1 month later:

    So sexy migrations made it to the rails edge trunk, but why didnt foregin key make it?

  • Dan Kubb, 2 months later:

    @Martin: I would bet we’ll never see “foreign_key” make it into edge rails (due to a belief by some core members that foreign keys are unecessary). However I bet what would be accepted is a patch that adds “belongs_to”, which basically just created an integer field (without creating a foreign key) pointed at the foreign table, named #{table_name}_id.

    The reason I think this is that we’ve seen some recent changes by DHH to add belongs_to/has_many type relations in routing. Its not too much of a stretch to bring the same general syntax to table migrations.

    The beauty of this approach is that plugins can be created that override the standard belongs_to method, and creates a real foreign key when possible.

  • Pei Mei, 5 months later:

    I just wanted to let you guys know that I have created a TextMate bundle for the Sexy Migrations plugin, which is one of my favorites and gets included in ever new project I start.

    You can get the Sexy Migrations Bundle at http://www.railsjitsu.com/blog/project-releases/sexy-migrations-textmate-bundle/ and I have included instructions for installing it.

    Thanks Chris and err.the_blog! You guys are my favorite Ruby on Rails blog!

  • Mohsin, 8 months later:

    Why not add the support for the additions of foreign key constraints as well to the database as the redonrails plugins are doing?

  • Thirty-two people have commented.
    Chime in.
    Sorry, no more comments :(
This is Err, the weblog of PJ Hyett and Chris Wanstrath.
All original content copyright ©2006-2008 the aforementioned.