Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple respond_with in rails that avoids 204 from PUT

I want to PUT to rails and avoid getting a 204. I am using this pattern:

class SomeController < ApplicationController
  respond_to :json

  def update
    # ...
    respond_with(some_object)
  end
end

However, when I do a put to update, I get a 204 back. I realize this is completely valid etc, but I explicitly want the content back. I can override it to some extent like this:

def update
  respond_with(some_object) do |format|
    format.json{render json: some_object}
  end
end

but this seems a bit too hands-on for rails. Is there any more idiomatic way of avoiding a 204 and requesting the full content to be sent back? This is Rails 3.2.

In summary: I want maximally idiomatic rails that avoids a 204.

like image 429
Peter Avatar asked Mar 31 '12 07:03

Peter


3 Answers

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.

like image 196
jpfuentes2 Avatar answered Sep 17 '22 21:09

jpfuentes2


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

like image 28
Ernesto Avatar answered Sep 18 '22 21:09

Ernesto


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
like image 26
Gabe Martin-Dempesy Avatar answered Sep 18 '22 21:09

Gabe Martin-Dempesy