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.