72

For ad hoc Rails tasks we have a few implementation alternatives, chief among which would seem to be:

script/runner some_useful_thing

and:

rake some:other_useful_thing

Which option should I prefer? If there's a clear favourite then when, if ever, should I consider using the other? If never, then why would you suppose it's still present in the framework without deprecation warnings?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Mike Woodhouse
  • 51,832
  • 12
  • 88
  • 127

8 Answers8

64

The difference between them is that script/runner boots Rails whereas a Rake task doesn't unless you tell it to by making the task depend on :environment, like this:

task :some_useful_task => :environment do
  # do some useful task
end

Since booting Rails is expensive, it might be worth skipping if you can avoid it.

Other than that, they are roughly equivalent. I use both, but lately I've used script/runner executing a script separately more.

Luke Francl
  • 31,028
  • 18
  • 69
  • 91
10

Passing parameters to a rake task is a pain in the butt, to say the least. You either need to resort to environment variables or a very hackish parameter system that is not intuitive and has lots of caveats.

If your task needs to handle command line arguments gracefully then writing a script is the way to go.

Luke Francl mentions script/runner booting up Rails. That's true. But if you don't want to boot up rails then just run the script as is without script/runner. So the only real difference between scripts and rake tasks are their aesthetics. Choose whatever feels right to you.

I use rake tasks for little tasks (one or two lines). Anything more complicated goes into the script/ directory. I'll break this rule if I think other developers will expect the code to live in one place over another.

Alfred Fazio
  • 956
  • 7
  • 10
10

FWIW there seems to be some movement away from using script runner in favor of rake:

Update (4/25/2009): I recommend using rake tasks as opposed to script/runner for recurring tasks.

Also, as per this post you can use rake for recurring tasks just fine:

If I then wanted this to run nightly on my production database at midnight, I might write a cronjob that looks something like this:

0 0 * * * cd /var/www/apps/rails_app/ && /usr/local/bin/rake RAILS_ENV=production utils:send_expire_soon_emails

Community
  • 1
  • 1
esilver
  • 27,713
  • 23
  • 122
  • 168
9

Corrected based on comment 2 down. Give them the karma!

FWIW - Rails 3.0+ changes how you initialize the Rails system in a standalone script.

require File.dirname(__FILE__) + '/config/environment'

As mentioned above you can also do:

rails runner script/<script name>

Or put all the code in a Rake task, but I have a lot of legacy code from Rails 2; so I didn't want to go down that path immediately.

Each has its advantages and disadvantages.

Ben Walding
  • 4,006
  • 2
  • 30
  • 28
5

One thing I've done is just write normal ruby scripts and put them in the script/maintenance directory.

All you need to do to load rails and get access to all your models, etc, is put require '../../config/environment.rb' at the top of your file, then you're away.

Orion Edwards
  • 121,657
  • 64
  • 239
  • 328
3

In Rails 3.0+, the config/environment.rb requires the config/application.rb, that requires the config/boot.rb.

So, to load an app in Rails 3, you still only have to require the environment.rb

ppires
  • 233
  • 1
  • 8
3

For one off commands script/runner can be fine. For anything repeated, a rake task is easier in the long-run, and has a summary if you forget what it does.

Daniel Morris
  • 6,852
  • 8
  • 25
  • 30
2

I got the impression script/runner was primarily for periodic tasks. E.g., a cron job that runs:

SomeClass.update_from_web('http://www.sourcefordata.gov/')
jlc
  • 176
  • 3
  • 1
    Nothing I've seen about a `runner` task requires or implies that it is for cron jobs primarily. Instead, I consider runner for tasks that have no need of the Rails presentation layer but want access to the DB and models, and that I wouldn't put into a controller or model because it makes no sense to put it there. – the Tin Man Jan 13 '11 at 14:41