Sometimes (okay, I’ll admit, pretty often), I’ll make a typo or forget a column when running a big
rails generate model or
scaffold command. Now I’m stuck with an incomplete bunch of files that I need to fix or delete.
For example, pretend I tried to generate a Report model but misspelled the name column as
$ bin/rails generate model Report naem:string invoke active_record create db/migrate/20150721233558_create_reports.rb create app/models/report.rb invoke test_unit create test/models/report_test.rb create test/fixtures/reports.yml
Oops! To fix my mistake, I could edit all of these files to correct the misspelling, or I could just undo the
rails generate command and re-run it.
To undo, run the same command a second time, but replace
$ bin/rails destroy model Report naem:string invoke active_record remove db/migrate/20150721233558_create_reports.rb remove app/models/report.rb invoke test_unit remove test/models/report_test.rb remove test/fixtures/reports.yml
It’s magic! My project is back to where I started, as if nothing happened. (If I had already run
db:migrate, then I would need to run
db:rollback first, then
Have you ever needed to execute Rails code from the command line? Maybe you need to write a cronjob to clean up some models with ActiveRecord.
Until recently I assumed a custom rake task was the best solution. Something like this:
- Write a rake task to do my ActiveRecord stuff
- Put code in
bundle exec rake mytaskin my crontab or wherever
runner command is just like
ruby -e: it executes an arbitrary string of Ruby code. Unlike
ruby -e, however, it first boots your Rails app and then runs your code in the full Rails environment. It’s just like running code inside the interactive
In other words, there is no need to write a Rake task. That’s unnecessary boilerplate.
Let’s say we need a cronjob to delete records of our Report model that are more than 3 months old. How would we do that using
First let’s add a scope in our existing
app/models/report.rb to handle the ActiveRecord logic:
class Report < ActiveRecord::Base def self.pending_deletion where("updated_at < ?", 3.months.ago) end end
Now performing the deletion from either the crontab or the command line is super easy:
bundle exec rails runner -e production "Report.pending_deletion.destroy_all"
Note that you can specify the desired Rails environment using the
--environment option. Otherwise it defaults to
$RAILS_ENV, if set).
Like other Rails commands, there are one-letter shortcuts:
I hope you find these commands to be useful in your Rails projects! More information can be found in the official Rails command line guide.