intridea/multi_json

json common error with Rails 2.0.0 and Cucumber

diabolo opened this issue · 23 comments

I'm getting an error trying to do a Rails 4, Ruby 2.0 project with Cucumber. Whilst I think Cucumber is mostly responsible for this, I think this highlights a potential flaw with multi_json.

What Cucumber is doing is using multi_json before a json gem is loaded, so multi_json is going into code in [13, 22] in lib/multi_json/adapters/json_common.rb. On line 18 the following code is called

::JSON.parse(string, options)

and this steps into ruby-2.0.0-p247/lib/ruby/2.0.0/json/common.rb:155

     154    def parse(source, opts = {})
  => 155      Parser.new(source, opts).parse
     156    end

where Parser is undefined

rdb:1) Parser
*** NameError Exception: uninitialized constant JSON::Parser

This and a comment in common.rb shown below:

# Returns the JSON parser class that is used by JSON. This is either
# JSON::Ext::Parser or JSON::Pure::Parser

makes me think that maybe multi_json should be setting the parser class in json_common.rb.

I hope this is a clear enough explanation. There is lots I don't understand about this code so apologies in advance if I have got things wrong

Tx

Andrew

I am having the same issue, with ruby2.0.0-p247. I do not receive the error in ruby2.0.0-p195.

I'm also having this issue with ruby2.0.0-p247. I haven't tried ruby2.0.0-p195

rwz commented

Can you provide steps to reproduce?

  1. Check out https://github.com/diabolo/hartl_tut
  2. Setup a clean ruby for 2.0.0-p247
    1. I use a trusted .rvmrc with content rvm use --create ruby-2.0.0-p247@hartl_tut > /dev/null
  3. Run bundle install
  4. Run cucumber

Stack trace is

/Users/andy/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/json/common.rb:155:in `parse': uninitialized constant JSON::Parser (NameError)
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/multi_json-1.7.8/lib/multi_json/adapters/json_common.rb:17:in `load'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/multi_json-1.7.8/lib/multi_json/adapter.rb:19:in `load'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/multi_json-1.7.8/lib/multi_json.rb:117:in `load'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin/i18n.rb:14:in `<class:I18n>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin/i18n.rb:6:in `<module:Gherkin>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin/i18n.rb:5:in `<top (required)>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin/lexer/i18n_lexer.rb:2:in `require'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin/lexer/i18n_lexer.rb:2:in `<top (required)>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin.rb:1:in `require'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/gherkin-2.12.0/lib/gherkin.rb:1:in `<top (required)>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/cucumber-1.3.5/lib/cucumber/cli/main.rb:2:in `require'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/cucumber-1.3.5/lib/cucumber/cli/main.rb:2:in `<top (required)>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/cucumber-1.3.5/bin/cucumber:11:in `require'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/gems/cucumber-1.3.5/bin/cucumber:11:in `<top (required)>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/bin/cucumber:23:in `load'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/bin/cucumber:23:in `<main>'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/bin/ruby_noexec_wrapper:14:in `eval'
    from /Users/andy/.rvm/gems/ruby-2.0.0-p247@hartl_tut/bin/ruby_noexec_wrapper:14:in `<main>'
rwz commented

@diabolo I'm getting completely different output:

hartl_tut ➤  bundle exec cucumber
DEPRECATION WARNING: ActionController::Integration is deprecated and will be removed, use ActionDispatch::Integration instead. (called from require at /Users/rwz/stuff/work/hartl_tut/features/support/env.rb:7)
DEPRECATION WARNING: ActionController::IntegrationTest is deprecated and will be removed, use ActionDispatch::IntegrationTest instead. (called from require at /Users/rwz/stuff/work/hartl_tut/features/support/env.rb:7)
You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it. (RuntimeError)
/Users/rwz/stuff/work/hartl_tut/features/support/env.rb:37:in `rescue in <top (required)>'
/Users/rwz/stuff/work/hartl_tut/features/support/env.rb:34:in `<top (required)>'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/rb_support/rb_language.rb:122:in `load'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/rb_support/rb_language.rb:122:in `load_code_file'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime/support_code.rb:180:in `load_file'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime/support_code.rb:83:in `block in load_files!'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime/support_code.rb:82:in `each'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime/support_code.rb:82:in `load_files!'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime.rb:183:in `load_step_definitions'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/runtime.rb:42:in `run!'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/lib/cucumber/cli/main.rb:47:in `execute!'
/Users/rwz/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/cucumber-1.3.5/bin/cucumber:13:in `<top (required)>'
/Users/rwz/.rbenv/versions/2.0.0-p247/bin/cucumber:23:in `load'
/Users/rwz/.rbenv/versions/2.0.0-p247/bin/cucumber:23:in `<main>'
Run options: --seed 8854

# Running tests:



Finished tests in 0.001498s, 0.0000 tests/s, 0.0000 assertions/s.

0 tests, 0 assertions, 0 failures, 0 errors, 0 skips

@rwz Sorry my bad, do a pull and try again. Pushed with wrong cucumber-rails gem for rails4.

rwz commented

Still no errors:

hartl_tut ➤  ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
hartl_tut ➤  bundle exec cucumber
Using the default profile...
0 scenarios
0 steps
0m0.000s
Run options: --seed 7865

# Running tests:



Finished tests in 0.001514s, 0.0000 tests/s, 0.0000 assertions/s.

0 tests, 0 assertions, 0 failures, 0 errors
rwz commented

@mattscilipoti, @trdulaney what about you guys, can you provide steps to reproduce?

please show ruby version

rwz commented

@diabolo it's 2.0.0p247. updated the comment

bizarre, just pulled it to another folder on my machine and I get exactly the same error I reported in my original post.

I can reproduce the error with these steps.

$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.3.0]
$ bundle exec cucumber
/Users/lbt/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/json/common.rb:155:in `parse': uninitialized constant JSON::Parser (NameError)
[...]
rwz commented

Ok, I need you to try this in an irb session:

> require 'json'
> JSON::VERSION
> defined?(JSON::Parser)
> require 'json/ext'
> defined?(JSON::Parser)

this is my output:

>> require 'json'
=> true
>> JSON::VERSION
=> "1.8.0"
>> defined?(JSON::Parser)
=> "constant"
>> require 'json/ext'
=> false
>> defined?(JSON::Parser)
=> "constant"
>> require 'json'
=> true 
>> JSON::VERSION
=> "1.7.7" 
>> defined?(JSON::Parser)
=> "constant" 
>> require 'json/ext'
=> false 
>> defined?(JSON::Parser)
=> "constant" 

I'm getting JSON::VERSION 1.7.7 as well

rwz commented

How do you get 1.7.7 when your project Gemfile.lock has json (1.8.0) in it?

I have one idea about that. If I run an IRB session with no json gem installed and without requiring anything I get a JSON::VERSION of 1.7.7. My original stack trace shows the code failing in ruby-2.0.0-p247/lib/ruby/2.0.0/json/common.rb. This seems to imply that there is a json implementation in ruby's library.

Perhaps the following explains, which is run in the project

bundle exec irb
2.0.0p247 :001 > defined?(JSON::Parser)
=> nil
2.0.0p247 :002 > JSON::VERSION
=> "1.7.7"
2.0.0p247 :003 > require 'json'
=> true
2.0.0p247 :004 > defined?(JSON::Parser)
=> "constant"
2.0.0p247 :005 >

Would be interested to see how the above behaves on your system.

@ rwz Investigating this a little further I think that line:51 of multi_json-1.7.8/lib/multi_json.rb should be

return :json_gem if defined?(::JSON) && defined?(::JSON::Parser)

or perhaps

return :json_gem if defined?(::JSON) && defined?(::JSON::JSON_LOADED)

currently its

return :json_gem if defined?(::JSON)

see (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html) for JSON_LOADED, also consider

➥  irb
2.0.0p247 :001 > ::JSON
 => JSON
2.0.0p247 :002 > ::JSON::JSON_LOADED
NameError: uninitialized constant JSON::JSON_LOADED
        from (irb):2
        from /Users/andy/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
2.0.0p247 :003 > require 'json'
 => true
2.0.0p247 :004 > ::JSON::JSON_LOADED
 => true

Thoughts ?

rwz commented

That makes sense. Will investigate later today.

rwz commented

Guys, could you check if current master fixes your problem? Will release a new version if it does.

Works for me, tx

+1 experiencing this as well. Current master fixes the problem... thanks. Please push new release?

I hit this when running guard-jasmine tests, actually, not cucumber. Here was the stack:

16:06:37 - INFO - Run all Jasmine suites
16:06:37 - INFO - Run Jasmine suite at http://localhost:49908/jasmine
16:06:49 - ERROR - Guard::Jasmine failed to achieve its <start>, exception was:
> [#FE79502548FE] NameError: uninitialized constant JSON::Parser
> [#FE79502548FE] ~/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/json/common.rb:155:in `parse'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.7.7/lib/multi_json/adapters/json_common.rb:16:in `load'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.7.7/lib/multi_json/adapter.rb:19:in `load'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.7.7/lib/multi_json.rb:130:in `load'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine/runner.rb:170:in `evaluate_response'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine/runner.rb:44:in `block in run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine/runner.rb:43:in `each'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine/runner.rb:43:in `inject'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine/runner.rb:43:in `run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine.rb:146:in `run_all'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-jasmine-1.17.0/lib/guard/jasmine.rb:117:in `start'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:99:in `block in run_supervised_task'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:97:in `catch'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:97:in `run_supervised_task'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:54:in `block (2 levels) in run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:175:in `block (3 levels) in scoped_guards'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:173:in `each'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:173:in `block (2 levels) in scoped_guards'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:172:in `catch'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:172:in `block in scoped_guards'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:170:in `each'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:170:in `scoped_guards'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:53:in `block in run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/lumberjack-1.0.4/lib/lumberjack.rb:31:in `unit_of_work'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/runner.rb:52:in `run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard.rb:211:in `block in start'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard.rb:387:in `block in within_preserved_state'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard.rb:384:in `synchronize'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard.rb:384:in `within_preserved_state'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard.rb:209:in `start'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/lib/guard/cli.rb:110:in `start'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/thor-0.18.1/lib/thor/command.rb:27:in `run'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/gems/guard-1.8.2/bin/guard:6:in `<top (required)>'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/bin/guard:23:in `load'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/bin/guard:23:in `<main>'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/bin/ruby_noexec_wrapper:14:in `eval'
> [#FE79502548FE] ~/.rvm/gems/ruby-2.0.0-p247/bin/ruby_noexec_wrapper:14:in `<main>'
rwz commented

@mikeatlas this was fixed and released 4 days ago.