October 1, 2019
This blog is part of our Rails 6 series.
When working in a team on a Rails application, we often bump into
PendingMigrationError
or other errors that need us to run a rails command,
rake task etc.
Rails introduced a way to resolve such frequent errors in development from error page itself.
Rails 6 added
ActiveSupport::ActionableError
module to define actions we want perform on errors, right from the error page.
For example, this is how PendingMigrationError
page looks like in Rails 6.
By default, a button is added on error screen that says Run pending
migrations. Clicking on this button would dispatch rails db:migrate
action.
Page will reload once migrations run successfully.
We can also define custom actions to execute on errors.
We need to include ActiveSupport::ActionableError
module in our error class.
We can monkey patch an existing error class or define custom error class.
#action
api is provided to define actions on error. First argument in
#action
is name of the action. This string would be displayed on the button on
error page. Second argument is a block where we can write commands or code to
fix the error.
Let's take an example of seeding posts data from controller, if posts not already present.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
if @posts.empty?
raise PostsMissingError
end
end
end
# app/errors/posts_missing_error.rb
class PostsMissingError < StandardError
include ActiveSupport::ActionableError
action "seed posts data" do
Rails::Command.invoke 'posts:seed'
end
end
# lib/tasks/posts.rake
namespace :posts do
desc 'posts seed task'
task :seed do
Post.create(title: 'First Post')
end
end
# app/views/posts/index.html.erb
<% @posts.each do |post| %>
<%= post.title %>
<% end %>
Let's check /posts
(posts#index
action) when no posts are present. We would
get an error page with an action button on it as shown below.
Clicking on seed posts data action button will run our rake task and create
posts. Rails will automatically reload /posts
after running rake task.
ActionDispatch::ActionableExceptions
middleware takes care of invoking actions from error page.
ActionableExceptions
middleware dispatches action to ActionableError
and
redirects back when action block has successfully run. Action buttons are added
on error page from
this middleware template.
Checkout the pull request for more information on actionable error.
If this blog was helpful, check out our full blog archive.