With a simple change, you can avoid loading Rails when running
bin/rake but still keep
bin/rake db:migrate, Hello
Rails 5 introduced a change to proxy Rake tasks through
bin/rails so that instead of calling
bin/rake for some commands (e.g.
bin/rake db:migrate) and
bin/rails for others (e.g.
bin/rails server), you can just always use
bin/rails for everything.
However, Rails will still load your Rails application when you run any Rake task due to the following lines in the generated
require_relative 'config/application' Rails.application.load_tasks
This isn’t too surprising once you realize they haven’t moved all of the old Rake tasks over to
bin/rails entirely, they’ve just made
bin/rails act as a proxy that just wraps the Rake tasks.
Skip loading Rails for non-Rails tasks
But what if you don’t want to load Rails for every Rake task? Say you have a Rake task that runs a formatter like Rubocop or Rufo, why should you have to load the entire Rails framework to run just that one task?
To avoid loading Rails for non-Rails related tasks, you can change those lines in your
Rakefile to this:
def load_rails require_relative 'config/application' Rails.application.load_tasks end load_rails if $0.match?(/rails/)
This uses the
$0 global variable that contains the name of the script being executed (e.g.
bin/rake) and then only loads Rails if it matches
Now you can run
bin/rake -T and it will quickly respond with just the non-Rails Rake tasks you’ve defined yourself.
And you can still run
bin/rails -T to load Rails and see all of the Rails-related Rake tasks.
What if you do want to load Rails
But say you have a Rake task that does depend on Rails…
You could make sure that you always call it with
bin/rails but instead you could explicitly tell Rake to load Rails before running it.
All you need to do is define another task that calls our
desc "Loads Rails application" task :load_rails do load_rails end
and declare it as a dependency:
task :my_task_that_needs_rails => [:load_rails] do # ... end
Now you can call
bin/rake my_task_that_needs_rails and Rake will load Rails first.
Should you actually do this?
I don’t know! I just thought of this and haven’t used it much in practice so there might be a good reason not to do this.
This seems to work on Rails 6.0.0.rc2 but future changes to how
bin/rails works internally in Rails could cause this to break so beware.