Skip to content

Rails Pro Tip: Invoke Command Line Commands From Rails Console

So there you have your command line prompt from Bash/Zsh/cmd.exe and there is so called Rails console which is basically IRB prompt with the Rails application loaded.

My tip suggests that you invoke some Rails commands, namely generator related commands and rake tasks, from the running Rails console. The reason to do so is clear and simple – it’s fast.

Real World Proof

Let’s do some math to prove the point. The last project I was involved with contains 171 models, 158 controllers and 572 migrations. Models and controllers were mostly generated together by single ./script/generate scaffold command. Migrations were generated with ./script/generate migration followed by rake db:migrate command. This accounts for about 1300 command line invocations.

Now sad statistics – running generator command from command line loads application environment which is not that cheap even on empty project

    rails3_app/ > /usr/bin/time -p rails generate migration just_testing
          invoke  active_record
          create    db/migrate/20100702124738_just_testing.rb
    real 7.54
    user 3.40
    sys 4.09
    
On the real world project I’m using as an example this time (because of many gems and other dependencies) was up to one minute.

On the other hand running the same command from Rails console (i.e. with environment already loaded) is instantaneous

    rails3_app/ > rails console
    Loading development environment (Rails 3.0.0.beta4)
    MyIrb loaded
    ruby-head > time { migration 'test9' }
          invoke  active_record
          create    db/migrate/20100702125251_test9.rb
    Time elapsed: 0.07000 user, 0.08000 system (0.14645 wall clock seconds)
    
(assuming environment loading took 30 seconds on average one can calculate the gain from using this technique for the whole project: 30 seconds * 1300 invocations/3600 = 10.8 hours :) )

Getting/Using It

Helpers that bring generator and rake commands to IRB prompt are available as part of my IRB configuration in console_in_console.rb file. Assuming it’s saved at ~/console_in_console.rb

    rails3_app/ > rails c
    ruby-head > load '~/console_in_console.rb'
    ruby-head > include MyIrb::Rails::ConsoleInConsole
    # Have fun now generating and destroying migrations, models, controllers
    # much faster than before

    ruby-head > model 'user login:string password:string'
          invoke  active_record
          create    db/migrate/20100702132016_create_users.rb
          create    app/models/user.rb
          invoke    test_unit
          create      test/unit/user_test.rb
          create      test/fixtures/users.yml
    
    ruby-head > migration 'migration_name'
          invoke  active_record
          create    db/migrate/20100702130723_migration_name.rb

    ruby-head > destroy_migration 'migration_name'
          invoke  active_record
          remove    db/migrate/20100702130723_migration_name.rb

    ruby-head > rake 'db:migrate'
    ==  Test11: migrating =========================================================
    ==  Test11: migrated (0.0000s) ================================================
    
And it works with Rails 2.x branch too!

blog comments powered by Disqus