Different results between command-line and test execution
I have a several classes that need to be extended to have a representation in JSON. Following the instruction of the JSON docs, and recognizing that I need the same code in many places, I created a pair of modules, one to be included in and one to extend the the class in question. So,
class Game
require 'assets/json_serializable'
require 'assets/json_deserializable'
include JSONSerializable
extend JSONDeserializable
attr_accessor :label
def initialize(label)
@label = label
end
def json_serialization_list
[label]
end
end
and
and
In irb, using the same (only) ruby on the machine:
whereas in the test:
gives:
What am I doing wrong/what should I examine that causes the json representation in the RubyMine to be different in the test than at the command line (in the irb environment)? I've had problems with what I would call a kind of caching behavior, where the results of tests change if I exit RubyMine and restart it. That was not the case here.
and
module JSONSerializable
require 'json/add/core'
def to_json(*a)
{
json_class: self.class.name,
data: json_serialization_list
}.to_json(*a)
end
end
require 'json/add/core'
def to_json(*a)
{
json_class: self.class.name,
data: json_serialization_list
}.to_json(*a)
end
end
and
module JSONDeserializable
def json_create(a)
new(*a['data'])
end
end
def json_create(a)
new(*a['data'])
end
end
In irb, using the same (only) ruby on the machine:
1.9.3p385 :002 > require 'app/models/game'
=> true
1.9.3p385 :003 > g = Game.new('7')
=> G7[OID:14415960]:
1.9.3p385 :004 > g2 = JSON.parse JSON.generate g
=> G7[OID:14336280]:
1.9.3p385 :005 > g2.eql? g
=> true
=> true
1.9.3p385 :003 > g = Game.new('7')
=> G7[OID:14415960]:
1.9.3p385 :004 > g2 = JSON.parse JSON.generate g
=> G7[OID:14336280]:
1.9.3p385 :005 > g2.eql? g
=> true
whereas in the test:
describe Game do
before { @game = Game.new('7') }
subject { @game }
before { @game = Game.new('7') }
subject { @game }
it "should have a JSON representation" do
c2 = JSON.parse JSON.generate @game
c2.should eql @game
end
end
c2 = JSON.parse JSON.generate @game
c2.should eql @game
end
end
gives:
expected: G7[OID:32512660]:
got: {"json_class"=>"Game", "data"=>["7"]}
(compared using eql?)
Diff:
@@ -1,2 +1,3 @@
-G7[OID:32512660]:
+"data" => ["7"],
+"json_class" => "Game"
got: {"json_class"=>"Game", "data"=>["7"]}
(compared using eql?)
Diff:
@@ -1,2 +1,3 @@
-G7[OID:32512660]:
+"data" => ["7"],
+"json_class" => "Game"
What am I doing wrong/what should I examine that causes the json representation in the RubyMine to be different in the test than at the command line (in the irb environment)? I've had problems with what I would call a kind of caching behavior, where the results of tests change if I exit RubyMine and restart it. That was not the case here.
Please sign in to leave a comment.
I should add that this is RM 4.5.4.
Also, the identical result is obtained (works at the irb console) whether executed inside or outside of RubyMine (here, from inside):
?> $LOAD_PATH << '~/Projects/MyApp' << '~/Projects/MyApp/lib'
$LOAD_PATH << '~/Projects/MyApp' << '~/Projects/MyApp/lib'
=> ["~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1/x86_64-linux", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1/x86_64-linux", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1", "~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/x86_64-linux", "~/Projects/MyApp", "~/Projects/MyApp/lib"] (editted for clarity)
?> require 'app/models/game'
require 'app/models/game'
=> true
?> g = Game.new('7')
=> G7[OID:16883820]:
?> g2 = JSON.parse JSON.generate g
=> G7[OID:16866140]:
?> g2.eql? g
=> true
Message was edited by: Derrell Durrett
Hi Derrell,
I think that this is not about RM but about test framework you are using (it is RSpec or something else?)
I'd expect that the problem is in should or eq matcher. I'd suggest to debug the test and see what is going wrong.
Regards, Oleg.
I'm trying to explore that possibilty, but since I've seen such behavior before (though, in the past, the difference has cleared up if I restart RubyMine), I thought I'd ask.
Also, as the behavior is clearly distinguished by the fact that JSON.parse returns different values in the irb environment versus the rspec environment, it can't be the rspec matchers themselves.
In a further attempt to understand the differences, I've wrapped the class so as to execute it, and I get more interesting results. To recap the earlier result, at the irb command line, both inside
and outside of RubyMine, I get a result that would be considered expected:
a = Thing.new
b = JSON.parse JSON.generate a
a.eql? b # ==> true
If I execute the same code in RubyMine (it is, modulo some quote marks, the same command line), I get:
a = Thing.new
b = JSON.parse JSON.generate a
a.eql? b # ==> true
So, something is different about the RubyMine environment.
This is the class:
class Thing
require 'assets/json_serializable'
require 'assets/json_deserializable'
include JSONSerializable
extend JSONDeserializable
attr_accessor :foo
def initialize(f)
@foo = f
end
def json_serialization_list
[foo]
end
def eql?(other)
other.is_a?(self.class) and foo.eql? other.foo
end
alias == eql?
a = Thing.new("bar")
b = JSON.parse JSON.generate a
puts a.eql? b
end
This is assets/json_serializable:
module JSONSerializable
require 'json/add/core'
# including this module requires defining
# json_serialization_list, which should be the list
# of attributes passed to the constructor
def to_json(*a)
{
json_class: self.class.name,
data: json_serialization_list
}.to_json(*a)
end
end
This is assets/json_deserializable:
module JSONDeserializable
def json_create(a)
new(*a['data'])
end
end
This is the command line (from in RubyMine-- the one for the command line has '' wrapping the argument to -e:
~/.rvm/rubies/ruby-1.9.3-p385/bin/ruby -I~/Projects/MyApp/ -I~/Projects/MyApp/lib -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) ~/Projects/MyApp/app/models/thing.rb
When I execute in RubyMine, the output of the 'puts' is false, and when at a terminal command line, it is true.
What could be different about the loaded modules (and how would I tell?) between the RubyMine environment, and the command line environment?
If I add a 'puts $LOAD_PATH' to the output, this is what I get:
(Inside RubyMine)
~/.rvm/gems/ruby-1.9.3-p385@global/gems/uglifier-1.3.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/sqlite3-1.3.7/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/shoulda-3.3.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/shoulda-matchers-1.4.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/shoulda-context-1.0.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/sass-rails-3.2.6/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rspec-rails-2.12.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rgl-0.4.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/stream-0.5/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rb-inotify-0.8.8/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rails-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/libnotify-0.5.9/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/jquery-rails-2.2.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/guard-spork-1.4.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/spork-0.9.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/guard-rspec-2.4.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rspec-2.12.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rspec-mocks-2.12.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rspec-expectations-2.12.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rspec-core-2.12.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/guard-1.6.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/terminal-table-1.4.5/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/pry-0.9.12/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/slop-3.4.3/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/method_source-0.8.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/lumberjack-1.0.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/listen-0.7.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/diff-lcs-1.1.3/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/coffee-rails-3.2.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/railties-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/thor-0.17.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rdoc-3.12.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/json-1.7.7/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rack-ssl-1.3.3/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/coffee-script-2.2.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/execjs-1.4.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/coffee-script-source-1.4.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/coderay-1.0.8/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/capybara-2.0.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/xpath-1.0.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/selenium-webdriver-2.29.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/websocket-1.0.7/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rubyzip-0.9.9/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/childprocess-0.3.8/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/ffi-1.4.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/ffi-1.4.0/ext/ffi_c
~/.rvm/gems/ruby-1.9.3-p385@global/gems/nokogiri-1.5.6/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/bourne-1.1.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/mocha-0.10.5/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/metaclass-0.0.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/bootstrap-sass-2.3.0.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/sass-3.2.5/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/bcrypt-ruby-3.0.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/activeresource-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/activerecord-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/tzinfo-0.3.35/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/arel-3.0.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/active_attr-0.7.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/actionmailer-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/mail-2.4.4/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/treetop-1.4.12/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/polyglot-0.3.3/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/mime-types-1.21/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/actionpack-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/sprockets-2.2.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/tilt-1.3.3/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/hike-1.2.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rack-test-0.6.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rack-cache-1.2/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rack-1.4.5/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/journey-1.0.4/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/erubis-2.7.0/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/activemodel-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/builder-3.0.4/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/activesupport-3.2.11/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/multi_json-1.6.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/i18n-0.6.1/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/rake-10.0.3/lib
~/Projects/MyApp
~/Projects/MyApp/lib
~/.rvm/gems/ruby-1.9.3-p385@global/gems/bundler-1.3.0.pre.8/lib
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1/x86_64-linux
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/x86_64-linux
(At the terminal command line)
~/Projects/MyApp
~/Projects/MyApp/lib
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby/1.9.1/x86_64-linux
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/site_ruby
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/vendor_ruby
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1
~/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/x86_64-linux
Any ideas?
Thanks in advance.
I've finally understood the source of my problem: different behavior of the to_json method between multi_json and json.
I can't yet figure out how to solve the resulting problem, but I at least understand why the difference in behavior between irb and execution in the context of the app.
Are you using Gemfile and bundler for the app? Usually them provide better control on environment.
Regards, Oleg.
I am using Gemfile and bundler.
As it turns out, once I knew enough to ask the right question, I discovered this is a well-known problem: http://stackoverflow.com/questions/683989/how-do-you-deal-with-the-conflict-between-activesupportjson-and-the-json-gem
So, I'm struggling to find the right magic to override the behavior of the JSON in ActiveSupport. But at least I know the problem isn't mysterious. Just annoying!