July 3, 2016
This blog is part of our Rails 5 series.
Before Rails 5, when we forget to add template for an action, we get
ActionView::MissingTemplate
exception.
class UsersController < ApplicationController
def index
@users = User.all
end
end
Started GET "/users" for ::1 at 2016-06-10 17:10:40 +0530
Processing by UsersController#index as HTML
Completed 500 Internal Server Error in 5ms
ActionView::MissingTemplate (Missing template users/index, application/index with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby]}...
Similarly, if we don't specify response for a POST request, we will also get
ActionView::MissingTemplate
exception.
class UsersController < ApplicationController
def create
@user = User.new(user_params)
@user.save
end
end
Started POST "/users"
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Max"}, "commit"=>"Create User"}
(0.1ms) begin transaction
SQL (2.7ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Max"], ["created_at", 2016-06-10 12:29:09 UTC], ["updated_at", 2016-06-10 12:29:09 UTC]]
(0.5ms) commit transaction
Completed 500 Internal Server Error in 5ms
ActionView::MissingTemplate (Missing template users/create, application/create with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby]}...
In Rails 5,
if we don't specify response for an action then Rails returns 204: No content
response by default.
This change can cause some serious implications during the development phase of
the app.
Let's see what happens with the POST request without specifying the response.
class UsersController < ApplicationController
def create
@user = User.new(user_params)
@user.save
end
end
Started POST "/users"
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Max"}, "commit"=>"Create User"}
(0.1ms) begin transaction
SQL (2.7ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "Max"], ["created_at", 2016-06-10 12:29:09 UTC], ["updated_at", 2016-06-10 12:29:09 UTC]]
(0.5ms) commit transaction
No template found for UsersController#create, rendering head :no_content
Completed 204 No Content in 41ms (ActiveRecord: 3.3ms)
Rails happily returns with 204: No content
response in this case.
This means users get the feel that nothing happened in the browser. Because Rails returned with no content and browser happily accepted it. But in reality, the user record was created in the database.
Let's see what happens with the GET request in Rails 5.
class UsersController < ApplicationController
def index
@users = User.all
end
end
ActionController::UnknownFormat (UsersController#index is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you're loading it in a web browser, we assume that you expected to actually render a template, not… nothing, so we're showing an error to be extra-clear. If you expect 204 No Content, carry on. That's what you'll get from an XHR or API request. Give it a shot.):
Instead of 204: No Content
, we get
ActionController::UnknownFormat
exception.
Rails is being extra smart here and hinting that we are probably missing
corresponding template for this controller action. It is smart enough to show us
this message as we requested this page via browser via a GET request. But if the
same request is made via Ajax or through an API call or a POST request, Rails
will return 204: No Content
response as seen before.
In general, this change can trip us in the development phase, as we are used to incremental steps like adding a route, then the controller action and then the template or response. Getting 204 response can give a feel of nothing happening where things have actually happened in the background. So don't forget to respond properly from your controller actions.
If this blog was helpful, check out our full blog archive.