Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is respond_with not returning json from my model?

Why doesn't respond_with respond with the json in this case? I'm invoking the action with an explicit .json (/tasks/4e3c1163a19d461203000106/items/4e4c27dfa19d46e0e400000a.json)

In my controller --

class Tasks::TasksController < Tasks::BaseController
  respond_to :html, :js, :json

  def update
    @task = @taskgroup.update_task(params[:id], params[:task])
    @taskgroup.save
    respond_with @task
  end
end

When I overrode to_json and added a breakpoint, it isn't hit. The response is:

{}

If I replace respond_with with an explicit call to to_json:

respond_with @task do |format|
  format.json { render json: @task.to_json }
end

The response is perfect:

{
"_id":"4e4c27dfa19d46e0e400000a",
"assigned_to":null,
"comments"  [{"_id":"4e4c2fd7a19d46e127000014", 
[SNIP]

It works fine in the later case, but I'd like to figure out why the first one doesn't work. This happens for other controllers and models in my app. Not sure if its a mongoid thing? (rails 3.0.9 / mongoid 2.1.8)

like image 381
ericvg Avatar asked Aug 18 '11 18:08

ericvg


1 Answers

Here is a monkeypatch I wrote to always respond_with what you tell it to do regardless of protocol. Be warned this does break RESTful best practices and if you respond_with in a RESTful manner then it may break. However if your JSON/XML responses are separate from the main application then it is useful and your other controllers will not break.

Usage, Include this in any controller to override the respond_with functionality.

class ApiController < BaseController
  include ValidResponder
end

Then anything that extends ApiController will include this functionality.

Save the following in app/lib/valid_responder.rb:

#Override restful responses.
module ValidResponder
  def self.included(base)
    ActionController::Responder.class_eval do
      alias :old_api_behavior :api_behavior
      define_method :api_behavior do |error|
        if controller.class.ancestors.include?(base)
          raise error unless resourceful?
          display resource
        else
          old_api_behaviour(error)
        end
      end
    end
  end
end

For reference, the actual method source is available here: http://api.rubyonrails.org/classes/ActionController/Responder.html#method-i-api_behavior

like image 137
Gazler Avatar answered Oct 22 '22 10:10

Gazler