This project is archived and is in readonly mode.

#4494 ✓stale
Dylan Markow

Ruby 1.9.2-head's JSON support breaks to_json for arrays of records

Reported by Dylan Markow | April 28th, 2010 @ 05:54 AM | in 2.3.10

Ruby 1.9.2 development just upgraded "ext/json" from 1.1.9 to 1.4.1 on 4/26/10 (See http://redmine.ruby-lang.org/repositories/revision/1?rev=27493). When using ruby-head downloaded/compiled since yesterday, running to_json on an array of results (for example, Post.order("id").to_json) gives the following error. Is this something that needs support on Rails' end, or should this be pushed upstream as a bug with ruby?

ArgumentError (wrong number of arguments (2 for 1)):
  app/controllers/projects_controller.rb:4:in `to_json'
  app/controllers/projects_controller.rb:4:in `index'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/abstract_controller/base.rb:153:in `process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/rendering.rb:11:in `process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/instrumentation.rb:29:in `block in process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/notifications/instrumenter.rb:18:in `instrument'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/notifications.rb:48:in `instrument'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/instrumentation.rb:28:in `process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/abstract_controller/callbacks.rb:18:in `block in process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/callbacks.rb:443:in `_run__419509867057456517__process_action__4237787885856004072__callbacks'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/callbacks.rb:404:in `_run_process_action_callbacks'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/callbacks.rb:88:in `run_callbacks'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/abstract_controller/callbacks.rb:17:in `process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/rescue.rb:8:in `process_action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/abstract_controller/base.rb:123:in `process'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/abstract_controller/rendering.rb:39:in `process'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal.rb:84:in `dispatch'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_controller/metal.rb:124:in `block in action'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/routing/route_set.rb:29:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/routing/route_set.rb:29:in `call'
  rack-mount (0.6.3) lib/rack/mount/route_set.rb:148:in `block in call'
  rack-mount (0.6.3) lib/rack/mount/code_generation.rb:89:in `block in recognize'
  rack-mount (0.6.3) lib/rack/mount/code_generation.rb:73:in `optimized_each'
  rack-mount (0.6.3) lib/rack/mount/code_generation.rb:88:in `recognize'
  rack-mount (0.6.3) lib/rack/mount/route_set.rb:139:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/routing/route_set.rb:458:in `call'
  warden (0.10.3) lib/warden/manager.rb:35:in `block in call'
  warden (0.10.3) lib/warden/manager.rb:34:in `catch'
  warden (0.10.3) lib/warden/manager.rb:34:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/activerecord-3.0.0.beta3/lib/active_record/query_cache.rb:31:in `block in call'
  /Users/dylan/.rvm/gems/ruby-head/gems/activerecord-3.0.0.beta3/lib/active_record/connection_adapters/abstract/query_cache.rb:35:in `cache'
  /Users/dylan/.rvm/gems/ruby-head/gems/activerecord-3.0.0.beta3/lib/active_record/query_cache.rb:11:in `cache'
  /Users/dylan/.rvm/gems/ruby-head/gems/activerecord-3.0.0.beta3/lib/active_record/query_cache.rb:30:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/activerecord-3.0.0.beta3/lib/active_record/connection_adapters/abstract/connection_pool.rb:365:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/head.rb:14:in `call'
  rack (1.1.0) lib/rack/methodoverride.rb:24:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/params_parser.rb:19:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/flash.rb:167:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/session/cookie_store.rb:107:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/cookies.rb:202:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/callbacks.rb:46:in `block in call'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/callbacks.rb:410:in `_run_call_callbacks'
  /Users/dylan/.rvm/gems/ruby-head/gems/activesupport-3.0.0.beta3/lib/active_support/callbacks.rb:88:in `run_callbacks'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/callbacks.rb:44:in `call'
  rack (1.1.0) lib/rack/sendfile.rb:105:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/show_exceptions.rb:48:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/railties-3.0.0.beta3/lib/rails/rack/logger.rb:13:in `call'
  rack (1.1.0) lib/rack/runtime.rb:17:in `call'
  rack (1.1.0) lib/rack/lock.rb:11:in `block in call'
  <internal:prelude>:10:in `synchronize'
  rack (1.1.0) lib/rack/lock.rb:11:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/actionpack-3.0.0.beta3/lib/action_dispatch/middleware/static.rb:30:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/railties-3.0.0.beta3/lib/rails/application.rb:132:in `call'
  /Users/dylan/.rvm/gems/ruby-head/gems/railties-3.0.0.beta3/lib/rails/application.rb:81:in `method_missing'
  /Users/dylan/.rvm/gems/ruby-head/gems/railties-3.0.0.beta3/lib/rails/rack/log_tailer.rb:15:in `call'
  rack (1.1.0) lib/rack/content_length.rb:13:in `call'
  rack (1.1.0) lib/rack/handler/webrick.rb:48:in `service'
  /Users/dylan/.rvm/rubies/ruby-head/lib/ruby/1.9.1/webrick/httpserver.rb:111:in `service'
  /Users/dylan/.rvm/rubies/ruby-head/lib/ruby/1.9.1/webrick/httpserver.rb:70:in `run'
  /Users/dylan/.rvm/rubies/ruby-head/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'

Comments and changes to this ticket

  • MikZ

    MikZ May 17th, 2010 @ 01:25 AM

    can confirm this error in ruby 1.9.1 and 1.9.2 with rails3 beta3

    commenting this line http://github.com/rails/rails/commit/00ee990443189649e481b2c30945e7... fixes it

  • Jeremy Kemper

    Jeremy Kemper May 17th, 2010 @ 01:39 AM

    The fix is to override the json lib's new Array#to_json also.

    We have no choice but to load the library, if present, to override its to_json pollution.

  • Rohit Arondekar

    Rohit Arondekar May 22nd, 2010 @ 07:20 AM

    An issue has been created by somebody on json's github: http://github.com/flori/json/issues#issue/21 let's see what happens there because it doesn't only break Rails. Also this commit has been referenced as the one to introduce the bug: http://github.com/flori/json/commit/82ed5b724fb36dcba884cdb2251d953...

  • Rasmus Rønn Nielsen

    Rasmus Rønn Nielsen June 12th, 2010 @ 05:07 PM

    I just installed ruby1.9.2-head and beta4 today. I think I'm getting the same error.

    { "test" => "test" } works, but { "test" => :test } fails...

    rasmus@machine1:/var/www/app1/current$ ruby -v
    ruby 1.9.2dev (2010-06-12 revision 28290) [x86_64-linux]
    rasmus@machine1:/var/www/app1/current$ rails c
    Loading development environment (Rails 3.0.0.beta4)
    ruby-1.9.2-head > { "test" => "test" }.to_json
     => "{\"test\":\"test\"}" 
    ruby-1.9.2-head > { "test" => :test }.to_json
    ArgumentError: wrong number of arguments (2 for 1)
        from /home/rasmus/.rvm/gems/ruby-1.9.2-head/gems/activesupport-3.0.0.beta4/lib/active_support/json/encoding.rb:133:in `to_json'
        from (irb):2:in `to_json'
        from (irb):2
        from /home/rasmus/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.beta4/lib/rails/commands/console.rb:47:in `start'
        from /home/rasmus/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.beta4/lib/rails/commands/console.rb:8:in `start'
        from /home/rasmus/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.beta4/lib/rails/commands.rb:23:in `<top (required)>'
        from script/rails:9:in `require'
        from script/rails:9:in `<main>'
    
  • Alex MacCaw

    Alex MacCaw June 13th, 2010 @ 03:09 AM

    Broken for me too. The issue is that the json lib is defining to_json methods on String/Hash/etc, which aren't ever being undefined. The following fixes it:

    module JSONFix
      def self.included(base)
        base.class_eval do
          undef to_json
          def to_json(options = nil)
            ActiveSupport::JSON.encode(self, options)
          end
        end
      end
    end
    
    [
      Hash, 
      Array, 
      String, 
      Numeric, 
      TrueClass, 
      FalseClass, 
      BigDecimal
    ].each {|c| c.send(:include, JSONFix) }
    
  • DavidBackeus

    DavidBackeus July 5th, 2010 @ 07:37 AM

    • Importance changed from “” to “Low”

    Broken in ruby 1.8.7 as well.

    $ irb -r rubygems
    >> require 'active_support/json'
    => true
    >> {:asdf => :asdf}.to_json
    ArgumentError: wrong number of arguments (2 for 1)
        from (irb):2:in `to_json'
        from (irb):2
    
  • Tim

    Tim July 6th, 2010 @ 10:04 AM

    What steps do I need to take to solve this problem? Please be verbose. I've attempted the suggestions here with no luck.

    I'm using Ruby 1.8.7 and Rails 2.3.8.

    Thanks!

    Sincerely,
    Tim

  • Nate Wiger

    Nate Wiger July 8th, 2010 @ 11:15 PM

    • Tag changed from json to activerecord 3.0, rails 3.0.0.beta4, activesupport, active_support, json

    The only way I've found to workaround this is to put this in environment.rb, after the initializer block

    class Array
      def to_json(*a)
        ActiveSupport::JSON.encode(self)
      end
    end
    

    This also works for Sinatra/etc if you put it in the main application.rb file (or whatever yours is called).

    I still don't understand why Rails needs to forcibly override to_json, when the JSON gem provides callbacks that can be used. The comments in the ActiveSupport source code even outline how they do nasty things to ensure the JSON gem's is clobbered.

    -Nate

  • Jeremy Kemper

    Jeremy Kemper July 8th, 2010 @ 11:49 PM

    • Milestone set to 2.3.9
    • State changed from “new” to “open”
    • Assigned user set to “José Valim”

    Nate, we begrudgingly chose to override jsongem's to_json after dealing with years of bugs due to its broken API.

    It assumes responsibility for all to_json usage and clobbers the method signature, using it as an internal builder API as well as a public JSON serialization API, then requiring users to pass along an *blob_of_important_but_opaque_args when defining a custom to_json.

    This means that any library that doesn't conform to the *blob_of_important_but_opaque_args method signature breaks when you require 'json'. That's fundamentally antisocial API behavior, and it caused enough issues that it was worth neutering.

    The jsongem library should keep its internal builder API tucked away someplace private, use a separate method like as_json to provide custom JSON representations of classes (that doesn't need the crazy method signature), and leave to_json as a simple, easily-overrideable wrapper method.

    So yes, the clobbering mentioned in the source comments is a fully intentional conspiracy to eradicate the to_json that jsongem wrought upon the Ruby world.

    José, you fixed this on master, right? Could you backport to 2-3-stable?

  • José Valim

    José Valim July 13th, 2010 @ 06:00 AM

    Yes, this is fixed in master. I tried to fix this on 2-3-stable though and could not reproduce the error in ActiveSupport test suite. If anyone could provide a failing test in AS, that would help a lot.

  • Jeremy Kemper

    Jeremy Kemper August 30th, 2010 @ 02:28 AM

    • Milestone changed from 2.3.9 to 2.3.10
  • José Valim

    José Valim September 2nd, 2010 @ 10:52 AM

    • State changed from “open” to “stale”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Referenced by

Pages