Search code examples
ruby-on-railsactiverecordruby-on-rails-3rails-migrations

Rails: How to create migration in subdirectory with Rails?


I'm writing a SaaS model application. My application database consist of two logic parts:

  • application tables - such as user, roles...
  • user-defined tables (he can generate them from UI level) that can be different for each application instance

All tables are created by rails migrations mechanism.

I would like to put user-defined tables in another directory:

  • db/migrations - application tables
  • db/migrations/custom - tables generated by user

so I can do svn:ignore on db/migrations/custom, and when I do updates of my app on clients servers it would only update application tables migrations.

Is there any way to achieve this in rails?


Solution

  • @Vasily thank's for your response. After reading it and couple more questions from stackoverflow I came up with this solution:

    Since I write my own generator to create user tables I included Rails::Generators::Migration in it so I can override next_migration_number method like this:

    def self.next_migration_number(dirname)
     if ActiveRecord::Base.timestamped_migrations
       Time.now.utc.strftime("custom/%Y%m%d%H%M%S")
     else
       "custom/%.3d" % (current_migration_number(dirname) + 1)
     end
    end
    

    Now all migrations generated by user are created in db/migrations/custom directory.

    Then I wrote normal rails migration that executes all migrations from db/migrations/custom directory:

    class ExecuteCustomMigrations < ActiveRecord::Migration
       MIGRATIONS_PATH='db/migrate/custom'
       def self.up
         Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].
         sort.map{|filename|require filename}.flatten.
         each{|class_name| const_get(class_name).up}
       end
    
       def self.down
         Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].sort.reverse.
         map{|filename|require filename}.flatten.
         each{|class_name| const_get(class_name).down}
       end
    end
    

    After user creates custom table i call this migration with this code:

    Rake::Task["db:migrate:redo"].execute("VERSION=20110108213453")