Simple respond_with in rails that avoids 204 from PUT
Solution 1:
I made a custom responder which always returns my JSON encoded resource even on PUT/POST.
I put this file in lib/responders/json_responder.rb
. Your /lib
dir should be autoloaded.
module Responders::JsonResponder
protected
# simply render the resource even on POST instead of redirecting for ajax
def api_behavior(error)
if post?
display resource, :status => :created
# render resource instead of 204 no content
elsif put?
display resource, :status => :ok
else
super
end
end
end
Now, explicitly modify the controller which requires this behavior, or place it in the application controller.
class ApplicationController < ActionController::Base
protect_from_forgery
responders :json
end
You should now get JSON encoded resources back on PUT.
Solution 2:
As a less invasive alternative, you can pass a json:
option to the respond_with
method invocation inside your controller update
action, like this:
def update
# ...
respond_with some_object, json: some_object
end
Granted it seems a bit unDRY having to repeat the object twice in the arguments, but it'll give you what you want, the json representation of the object in the response of a PUT request, and you don't need to use the render json:
way, which won't give you the benefits of responders.
However, if you have a lot of controllers with this situation, then customizing the responders, as jpfuentes2 showed in the accepted anwser, is the way to go. But for a quick single case, this alternative may be easier.
Source: https://github.com/plataformatec/responders/pull/115#issuecomment-72517532
Solution 3:
This behavior seems intentional to fall in line with the HTTP spec, and "ideally" you should be firing off an additional GET request to see the results. However, I agree in the real world I'd rather have it return the JSON.
@jpfuentes2's solution above should do the trick (it's very similar to the pull request below), but I'm hesitant to apply anything that's patching rails internals, as it could be a real pain to upgrade between major versions, especially if you don't have tests for it (and let's face it, developers often skimp on controller tests).
References
- https://github.com/rails/rails/issues/9862
- https://github.com/rails/rails/pull/9887
Solution 4:
Just to clarify, you do not need the responders gem to do this... You can just do:
config/initializers/responder_with_put_content.rb
class ResponderWithPutContent < ActionController::Responder
def api_behavior(*args, &block)
if put?
display resource, :status => :ok
else
super
end
end
end
and then either (for all updates actions to be affected):
class ApplicationController < ActionController::Base
def self.responder
ResponderWithPutContent
end
end
or in your action:
def update
foo = Foo.find(params[:id])
foo.update_attributes(params[:foo])
respond_with foo, responder: ResponderWithPutContent
end
Solution 5:
What's wrong with simply doing:
def update
some_object = SomeObject.update()
render json: some_object
end