Reputation: 51844
The following code sample is part of a Rails 3.2.16 app running on Ruby 1.9.3p484.
Whenever a new location is created or one is updated a message should be sent as defined in the after_filter
.
class LocationController < InheritedResources::Base
respond_to :json
after_filter :notify_location_contact, only: [:create, :update]
def create
@location.user = current_user if current_user
create!
end
def update
update!
end
private
def notify_location_contact
message = MailForm.new
deliver_location_message(message)
end
def deliver_location_message(location_message)
begin
if location_message.deliver
render json: { message: "Successfully delivered" }, status: 201
else
render json: { error: "Delivery failure" }, status: 500
end
rescue => e
if e.is_a?(ArgumentError)
render json: { error: "Invalid Recipient" }, status: 422
else
render json: { error: e.message }, status: 500
end
end
end
end
The message itself is sent. Though, deliver_location_message
first renders the "Successfully delivered" block and after the last block rendering the error message. This causes an internal server error:
Completed 500 Internal Server Error
AbstractController::DoubleRenderError - Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
For sending the message the mail_form gem ~> 1.5.0
is used.
The DoubleRenderError seems to happen because create
and update
both render the JSON response when they finished there work. After, .deliver
renders its JSON response to inform about success or failure.
Upvotes: 0
Views: 586
Reputation: 38645
As the error points out you need to return after calling render
because you have multiple calls to render
in your deliver_location_message(message)
method. The reason for the error is because Rails continues execution until the end of the method regardless of render or redirect.
Please try the following. Note the return
on each render
line.
def deliver_location_message(message)
begin
if message.deliver
# Here
return render json: { message: "Successfully delivered" }, status: 201
else
# Here
return render json: { error: "Delivery failure" }, status: 500
end
rescue => e
if e.is_a?(ArgumentError)
# Here
return render json: { error: "Invalid Recipient" }, status: 422
else
# Here
return render json: { error: e.message }, status: 500
end
end
end
Alternative syntax to:
return render json: { message: "Successfully delivered" }, status: 201
is:
render json: { message: "Successfully delivered" }, status: 201 and return
Upvotes: 0