Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.eql explodes with thinky #45

Open
kaievns opened this issue May 16, 2016 · 12 comments
Open

.eql explodes with thinky #45

kaievns opened this issue May 16, 2016 · 12 comments

Comments

@kaievns
Copy link

kaievns commented May 16, 2016

hey andri, i thought i'd report this one. if i have two instances of a thinky model and then try to compare them against each other with .eql like so:

const user1 = yield User.get("123").run();
const user2 = yield User.get("123").run();

user1.must.eql(user2);

it explodes and complains about JSON serialization issues

ReqlDriverError: `toJSON` takes 0 argument, 1 provided after:
r.table("User")
      at Term._arity (node_modules/rethinkdbdash/lib/term.js:3014:11)
      at Term.toJsonString (node_modules/rethinkdbdash/lib/term.js:2765:10)
      at Query.(anonymous function) [as toJSON] (node_modules/thinky/lib/query.js:814:60)
      at Model.(anonymous function) [as toJSON] (node_modules/thinky/lib/model.js:722:32)
      at Object.stringify (native)
      at exports.stringify (node_modules/must/lib/index.js:38:19)
      at Must.assert (node_modules/must/must.js:1151:13)
      at Must.eql (node_modules/must/must.js:544:8)
      at Context.<anonymous> (test/models/user_test.js:53:19)
      at next (native)
      at onFulfilled (node_modules/co/index.js:65:19)
@moll
Copy link
Owner

moll commented May 16, 2016

Hey! Thanks for sharing. Is it me or is this actually Thinky's weird behavior when its toJSON gets called by JSON.stringify? That, or RethinkDBDash's. I suspect the problem is that JSON.stringify passes the key it's serializing the object under to toJSON, but either of the two are not prepared to handle that.

@moll
Copy link
Owner

moll commented May 16, 2016

@kaievns
Copy link
Author

kaievns commented May 16, 2016

i don't really know who's fault that is, but i can tell you that it works like a charm in both chaijs and expectjs :) Also, i can tell you that:

Object.assign({}, user1).must.eql(Object.assign({}, user2));

is a total mood killer, so I thought I'd let you know about the problem

@moll
Copy link
Owner

moll commented May 16, 2016

I wouldn't do the above either. :) It's probably not even guaranteed to return the same properties with it ignoring inherited properties and all.

I don't know why Chai and Expect work. I take it they don't call JSON.stringify. That happens only when printing the model out, right? As a quick fix I think you can overwrite Thinky's Model.prototype.toJSON to do the above Object.assign trick for you.

Anywho, I created neumino/thinky#501 for you.

@kaievns
Copy link
Author

kaievns commented May 16, 2016

thanks! :)

@moll
Copy link
Owner

moll commented May 16, 2016

To confirm just in case, the above happens only when the assertion failed and it's printing the model out for the diff, right?

@kaievns
Copy link
Author

kaievns commented May 16, 2016

no, not really. it happens even when two equal records are compared (as show in the first example)

i don't think it even gets to the assertion part. it seems that the failure happens when you try to export data for comparison or something like that

@moll
Copy link
Owner

moll commented May 16, 2016

For it to get to the stringifying part of Must.prototype.assert it had to have been unequal in Must.prototype.eql's view I suspect. As you know, equality of objects in JavaScript is tricky because due to lack of traits, operator overloading or equivalent language features, we need to rely on conventions. The conventions Must's eql adheres to are based on https://github.com/moll/js-egal, with the addition that non-value objects are compared recursively if they're from the same constructor (i.e same "class"). I presume the latter is applicable to models from Thinky.

If you print the objects out with Util.inspect, do they seem equivalent to you?

console.log(require("util").inspect(user1, {depth: null}))
console.log(require("util").inspect(user2, {depth: null}))

Although Util.inspect ignores inherited properties, I doubt Thinky's mutating anything there per instance.

@kaievns
Copy link
Author

kaievns commented May 17, 2016

here's what i have when i dump it

model {
  email: '[email protected]',
  id: '0cb2f830-04f9-474c-b011-f4ea2b814bbe',
  passwordHash: 'JUZpKmmi5W2BmBphQnP8qThe8V4=',
  passwordSalt: 'brLUp2EOJ3yZfd7o' }
model {
  email: '[email protected]',
  passwordSalt: 'brLUp2EOJ3yZfd7o',
  passwordHash: 'JUZpKmmi5W2BmBphQnP8qThe8V4=',
  id: '0cb2f830-04f9-474c-b011-f4ea2b814bbe' }

those are not ReQL query like @neumino said. those are instances of a User model. and they are identical

@neumino
Copy link

neumino commented May 17, 2016

How did you declare your model?

@kaievns
Copy link
Author

kaievns commented May 17, 2016

@neumino the usual

const User = thinky.createModel("User", {
  email: String,
  passwordSalt: String,
  passwordHash: String
});

is there any other way to declare it?

@neumino
Copy link

neumino commented May 18, 2016

Hum, can you provide a whole script that triggers this error?
I'm not super familiar with js-must, so that would help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants