Search code examples
ruby-on-railsjsonbundler

Rails render :json => [1,2,3] behaving differently in production (json root)


I'm seeing some weird behaviour in my Rails app. I'm running ruby 1.9.2-p290, and I have this sort of controller:

class NumbersController < ApplicationController

  def index
    render :json => [1,2,3]
  end

end

Imagine I run the servers like this to demonstrate the problem:

$ rails s # This one runs in "development" on port 3000
$ RAILS_ENV=production rails s -p 2999 # This one runs in "production" on port 2999

In development or test mode, my result would be

$ curl localhost:3000/numbers # development
{numbers: [1,2,3]} # The root is being included in the json, as inferred from the controller name.
$ curl localhost:2999/numbers # production
[1,2,3] # No root in the JSON

I've been over the app with a fine tooth comb and there are no obvious configuration differences that look like they would affect json between development and production. Also, no lines like "if Rails.env === 'production'"

I'm guessing that different gems are being required, e.g. for assets, which are changing the behaviour of render :json => ... . I've inspected the versions of the "json" and "multi_json" gems from within the running apps, and they are the same (1.7.5 and 1.3.6 respectively, and multi_json uses the same adapter.). How do I find out exactly which gems are required from within the app while it is running? Also, does anyone have any alternative explanations?

EDIT: I'm running Rails 3.1.1 and the assets part of my Gemfile is:

group :assets do
  gem "ember-rails"
  gem "jquery-rails"
  gem "less", "2.0.7"
  gem "less-rails", "2.0.2"
  gem 'uglifier'
end

Solution

  • I found a workaround here: include_root_in_json from controller

    The solution:

    render :json => {:numbers => [1,2,3]}, :root => false # If you want the root
    

    :root => true isn't being respected in production. I suspect the as_json or to_json has been overridden incorrectly in that environment.

    I'm still not happy though, because I can't rely on render :json => [1, 2, 3].