Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

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

#4494

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'

Reported by Dylan Markow · April 28th, 2010 @ 05:54 AM

State: stale
Milestone: 2.3.10
Assigned to: José Valim José Valim
Importance: Low

Activity

  1. MikZ
    MikZ

    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

    May 17th, 2010 @ 01:25 AM

  2. Jeremy Kemper
    Jeremy Kemper

    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.

    May 17th, 2010 @ 01:39 AM

  3. Rohit Arondekar
    Rohit Arondekar

    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...

    May 22nd, 2010 @ 07:20 AM

  4. Rasmus Rønn Nielsen
    Rasmus Rønn Nielsen

    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>'
    

    June 12th, 2010 @ 05:07 PM

  5. Alex MacCaw
    Alex MacCaw

    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) }
    

    June 13th, 2010 @ 03:09 AM

  6. DavidBackeus
    DavidBackeus
    • 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
    

    July 5th, 2010 @ 07:37 AM

  7. Tim
    Tim

    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

    July 6th, 2010 @ 10:04 AM

  8. Nate Wiger
    Nate Wiger
    • 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

    July 8th, 2010 @ 11:15 PM

  9. Jeremy Kemper
    Jeremy Kemper
    • 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?

    July 8th, 2010 @ 11:49 PM

  10. José Valim
    José Valim

    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.

    July 13th, 2010 @ 06:00 AM

  11. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.3.9 to 2.3.10

    August 30th, 2010 @ 02:28 AM

  12. José Valim
    José Valim
    • State changed from open to stale

    September 2nd, 2010 @ 10:52 AM