-
-
Notifications
You must be signed in to change notification settings - Fork 242
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
Issue with Fixnum and Float in enum #219
Conversation
I fixed that by simply adding hyperschema validators for draft1 and 2 according to the one already present for draft4. Could that have done any harm? And I have no idea why it is not required for draft3. Another thing which occurred to me: Because I renamed some test, it failed. That was because that test was overwritten by another one with the same method name. Is there a way we can Minitest have raising an exception when a test method is about to be redefined in a test class? |
I don't think minitest or test unit would be able to raise an exception if a test is redefined, because it's just a plain old Ruby object. I imagine the best we can do is to make sure tests are run with warnings enabled. I've just raised a pull request to do that |
assert_valid schema, data | ||
end | ||
|
||
def test_enum_integer_integer_excludes_float |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be test_enum_integer_excludes_float ?
All sounds fine to me. I'm not sure why any? works but include does not (if it's just an array) but I'm not too concerned 👍 |
I've just realised why the change from include? to any? works. In the way you have defined any, we check "data == value" (where value is an element in the array). Ruby's Array#include? method checks "value == data". By reversing the order we change which object's == method is called. It looks like whatever data#== is it is not behaving the same as value#==. Ideally == should be symmetric and the two should be equivalent. Perhaps a better fix to this bug would be to correct data#== (but I have no idea what class data is in this instance) |
That seems not to be the cause, because the tests still pass when I use |
Do you have any idea what class enum is?
|
Good one @iainbeeston :-), the problem is not the type of the values but of I don't know what the performance impact for this change is. The current fix would make it obsolete, so we could just go back to use an array here and |
It might be nice to remove arrayset completely in 3.0. When json-schema was
written it had to work with ruby 1.8, where hashes are unordered. If we
drop 1.8 support in 3.0 then we could potentially replace ArraySet with a
simple hash (which can emulate an ordered set/bag)
|
Actually we don't even need ordering. So a Set would do. Which goes back to
@hoxworth really, and why we need ArraySet (rather than using a Set)
|
But that still wouldn't fix the issue here because a set containing 1 responds with For the existing array set this could look like this: class ArraySet < Array
def include?(obj)
# On first invocation create a HASH (yeah, yeah) to act as our set given the array values
if !defined? @array_values
@array_values = {}
self.each do |x|
@array_values[x] = nil
if x.is_a?(Numeric) && x.to_i == x
other_numeric = x.class == Float ? x.to_i : x.to_f
@array_values[other_numeric] = nil
end
end
end
@array_values.has_key? obj
end
end |
Oh I see. Set#include? relies on Hash#include?, which checks inclusion
based on #hash, 1.0.hash is not the same as 1.hash, so Set#include?
doesn't work as we expect.
Set supposedly implements enumerable, which explicitly checks inclusion
using ==. So either the ruby documentation is wrong or there's a bug in
ruby.
|
The docs for Set explicitly state how equality is handled:
|
Set implements Enumerable, which states:
Returns true if any member of enum equals obj. Equality is tested using ==.
http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-include-3F
|
Then we should probably submit this contradiction somwhere™. Where is the place for such a thing? And we need a decision for json-schema for which I'd like to wait what @hoxworth has to say. |
I'll file a pull request to ruby later. Generally it seems that if the
implementation contradicts the documentation, the docs are wrong.
|
In this case I feel like we should treat every number in an enum and all comparisons in the enum as a |
@hoxworth, probably because otherwise schema validation fails with the following message?
|
@RST-J Ah yes, that is exactly why - |
I've been thinking about this. Array#include? returns true if any element
== the argument. ArraySet#include? returns true if any element eql? the
argument. If ArraySet is supposed to be a drop-in replacement for Array,
and is mainly used for it's include? method, then should that method
really behave differently?
I would argue not.
Perhaps a safer way to optimise include? would be to store a sorted version
of the array in an instance variable (where we now store a set) then
performing a binary search, but we'd have to implement the binary search
ourselves (bsearch is not in Ruby 1.8 or 1.9)
|
I agree, it should behave like Array and that is what it does now (unless there is another case we haven't figured out yet). Using a binary search won't work because we cannot order the set with reasonable effort in the general case. The spec says:
So we'd need to come up with a function that assigns equal arguments the same value. Do you have a serious concern about my last change, @iainbeeston? P.S.:
|
I think what you've committed is the best we can do right now. The only
Otherwise it's 👍 from me |
I didn't find any require statement for Set with grep, I don't know why it worked. But I added a require statement for consistency. |
FYI I've updated ruby's rdoc for set to make it explicit that it doesn't use == for include? ruby/ruby#831 |
Looks mostly fine. One question: why do the new hyperschemas include |
I didn't spent thoughts here, just copied hyper schema validator for draft4. I think, generally you are right, the default validator should only be set once and it should be draft4. So the right step is to not do it in the two ne hyper schema validators - I'll remove that - and also not doing it in the hyper-schema-draft 4. I'll prepare another PR to remove that. |
I removed all default registrations, also for draft4 in the extra commit. |
Good stuff RST-J! |
👍 |
a92f580
to
7375be1
Compare
Issue with Fixnum and Float in enum
I found out that there is a problem with Fixnum und Float values not being treated as equal when checking against an enum list, which they should if the required type is number as it includes all integers.
I don't know why
include?
fails here.And another thing. There are currently two tests failing for draft-1 and draft-2 when they are called with schema validation. The error is:
JSON::Schema::SchemaError: Schema not found: http://json-schema.org/draft-02/hyper-schema#
Any quick hints how to fix that? I'm in the office and cannot dig into that right now.