Rails 4 - How to render JSON regardless of requested format?
Asked Answered
C

7

31

I'd like a Rails controller (all of them, actually, it's an API) to render JSON always always.

I don't want Rails to return "route not found", or try and fail to find an HTML template, or return 406. I just want it to automatically and always render JSON, e.g. from a RABL or JBuilder view.

Is this possible? Related questions seem to have answers that have the aforementioned downsides.

Chesna answered 30/5, 2014 at 3:37 Comment(0)
Q
50

You can add a before_filter in your controller to set the request format to json:

# app/controllers/foos_controller.rb

before_action :set_default_response_format

protected

def set_default_response_format
  request.format = :json
end

This will set all response format to json. If you want to allow other formats, you could check for the presence of format parameter when setting request.format, for e.g:

def set_default_response_format
  request.format = :json unless params[:format]
end
Quick answered 30/5, 2014 at 3:49 Comment(4)
Naturally, this can be placed in /app/controllers/application_controller.rb to have an application-wide effect (strictly if your app is an API)Dobbins
FWIW, I just tried this solution in Rails 5 (with html format, vs json) and Rails wouldn't take :html, it needed 'html' as a string. Not sure why it wouldn't accept a symbol for request.format, but once I changed it to 'html' from :html it worked great.Carbohydrate
in rails 5 I use request.format = :json unless request.format.symbolRustproof
or inline it: ``` before_action { request.format = :json unless request.format } ```Gouge
P
14

You can use format.any:

def action
  respond_to do |format|
    format.any { render json: your_json, content_type: 'application/json' }
  end
end
Permafrost answered 1/10, 2014 at 20:12 Comment(0)
D
7

It's just:

render formats: :json
Donnelldonnelly answered 17/8, 2019 at 17:17 Comment(2)
@Akaisteph7 Not quite sure what you mean. This answer is clearly different from other.Donnelldonnelly
What I mean is that you should add some context to your answer.Antagonize
S
0

I had similar issue but with '.js' extension. To solve I did the following in the view: <%= params.except!(:format) %> <%= will_paginate @posts %>

Sihunn answered 6/12, 2016 at 17:37 Comment(0)
E
0

I tried the above solutions and it didn't solve my use case. In some of the controllers of my Rails 4.2 app, there was no explicit render called. For example, a service object was called and nothing was returned. Since they are json api controllers, rails was complaining with a missing template error. To resolve I added this to our base controller.

  def render(*args)
    options = args.first
    options.present? ? super : super(json: {}, status: :ok)
  end

It's a large app I'm converting to Rails 5, so this is just a safety measure as I removed the RocketPants gem that seemed to do this automatically.

As a note, my controllers inherit from ActionController::Base

Electroballistics answered 9/10, 2020 at 22:53 Comment(0)
T
0

I usually put it like this and it works. The lambda symbol ( => ) near :json is important.

def greet_action
  msg = {:greet => "hello"}
  render :json => msg
end
Tamtama answered 26/9, 2023 at 13:34 Comment(0)
O
-1

Of course:

before_filter :always_json

protected

def always_json
  params[:format] = "json"
end

You should probably put this in a root controller for your API.

Outspan answered 30/5, 2014 at 3:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.