Running and Destroying Rails

Did you know that you can undo a Rails generator with the “destroy” command? Or execute arbitrary code in a Rails app from a cronjob using “runner”? Here’s a quick introduction to “running” and “destroying” with Rails!

Undo rails generate with rails destroy

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 naem:

$ 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 generate with destroy.

$ 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 rails destroy.)

Execute code with rails runner

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.

The rake solution. Until recently I assumed a custom rake task was the best solution. Something like this:

Better: use rails runner! The 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 rails console.

In other words, there is no need to write a Rake task. That’s unnecessary boilerplate.

An example. 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 rails runner?

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)

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 -e or --environment option. Otherwise it defaults to development (or $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.