1

I need to write some code in one place (base_controller.rb which inherits from application_controller.rb) that wraps all outgoing json responses from controllers in a json object before returning.

In my Rails (5.x.x) application, there are ~100 endpoints serving different types of data (json objects, arrays, array of arrays etc). Due to a recent requirement, I have to wrap them all in a parent object.

Previous state:

some_controller.rb

return_obj = { key: value }
render json: return_obj

Expected state:

some_controller.rb will return { key: value }, but this will be intercepted by base_controller.rb which in turn will return something like { payload: { key: value }, other_info: info }

aryaag
  • 110
  • 8

1 Answers1

4

Option-1: We have something similar in our setup, what we do is, that we have a method named render_response in our base_api_controller file. Which looks something like:

  def render_response(render_params)
    # controller_name, action_name will give you controller and action which rendered the response.
    # so you can decide weather to process anything or just render

    render_params[:json] = { payload: render_params[:json] }
    render render_params
  end

And your controller action will convert to something like:

return_obj = { key: value }
render_response json: return_obj

Personally(and obviously) I like first approach because it is explicit and looking at the controller code gives us the information that we are processing the response further.

Option-2: If you don't like replacing render with render_response you can follow this guide to setup a rack middleware, which is also dead simple. but you will have to place checks of controllers if you don't want to do any updates for some specific controller actions. And also note that it will be automatic, so without anyone noticing(lets see someone completely new to your code) it will be changing the response. Which i personally don't like much.

Zia Ul Rehman Mughal
  • 2,119
  • 24
  • 44
  • What if we had an `after_action` method called `handle_response` in the `base_controller` and let `handle_response` make changes to the response being rendered? That way there would be no need to change the `render` to `render_response`. Although, I agree that a middleware would be better for this use case, I was just curious to know the limitations of doing so in an `after_action`. – Anuj Khandelwal Jun 26 '19 at 12:14
  • @AnujKhandelwal I don't think that will be any issue, we are doing some other explicit stuff as well in the render_reponse method and we like things to be more explicit and more magic, thats why we are doing it explicitly. I guess its just matter of choice. – Zia Ul Rehman Mughal Jun 26 '19 at 12:19
  • Yeah. That makes sense. Explicit is definitely better than implicit, especially with all the Rails magic. – Anuj Khandelwal Jun 26 '19 at 12:21