rails

2 Under-Appreciated Rails Commands

Easily undo scaffolding mistakes with rails destroy and execute arbitrary code from the command-line with rails runner.

Undo scaffolding 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:

  • Write a rake task to do my ActiveRecord stuff
  • Put code in lib/tasks/mytask.rake
  • Run bundle exec rake mytask in my crontab or wherever

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

Shortcuts

Like other Rails commands, there are one-letter shortcuts:

  • rails d → rails destroy
  • rails r → rails runner

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.

Share this? Copy link

Feedback? Email me!

Hi! 👋 I’m Matt Brictson, a software engineer in San Francisco. This site is my excuse to practice UI design, fuss over CSS, and share my interest in open source. I blog about Rails, design patterns, and other development topics.

Recent articles

RSS
View all posts →

Open source projects

mattbrictson/nextgen

Generate your next Rails app interactively!

11
Updated 23 hours ago

mattbrictson/tomo

A friendly CLI for deploying Rails apps ✨

360
Updated 23 hours ago

More on GitHub →