Skip to content

Commit a5d0bbf

Browse files
MONGOID-5289 - Faster Regex for numeric mongoization + bug fixes (#5222)
* Add faster Regex for numeric detection * Add more specs to cover fixed bugs * More robust specs * Fix text * Add test case for empty string; fix some spec descriptions Co-authored-by: shields <[email protected]>
1 parent 0dddb50 commit a5d0bbf

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

lib/mongoid/criteria/queryable/extensions/numeric.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ module ClassMethods
5151
#
5252
# @return [ Object ] The converted number.
5353
def __numeric__(object)
54-
object.to_s =~ /(\A[-+]?[0-9]+\z)|(\.0+\z)|(\.\z)/ ? object.to_i : Float(object)
54+
object.to_s.match?(/\A[-+]?[0-9]*[0-9.]0*\z/) ? object.to_i : Float(object)
5555
end
5656

5757
# Evolve the object to an integer.

spec/mongoid/criteria/queryable/extensions/numeric_spec.rb

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,108 @@
1111
end
1212

1313
describe "#__numeric__" do
14-
1514
let(:actual) { host.__numeric__(str) }
1615

1716
context "when the string is a whole number" do
18-
1917
let(:str) { '123' }
2018

21-
it "returns the value as integer" do
19+
it "returns the value as an integer" do
2220
expect(actual).to eq(123)
21+
expect(actual).to be_a Integer
2322
end
2423
end
2524

2625
context "when the string is a floating point number" do
27-
2826
let(:str) { '123.45' }
2927

3028
it "returns the value as a float" do
3129
expect(actual).to eq(123.45)
30+
expect(actual).to be_a Float
3231
end
3332
end
3433

35-
context "when the string is a dot only" do
34+
context "when the string is a floating point number with a leading dot" do
35+
let(:str) { '.45' }
3636

37+
it "returns the value as a float" do
38+
expect(actual).to eq(0.45)
39+
expect(actual).to be_a Float
40+
end
41+
end
42+
43+
context "when the string is a dot only" do
3744
let(:str) { '.' }
3845

3946
it "returns zero" do
4047
expect(actual).to eq(0)
48+
expect(actual).to be_a Integer
4149
end
4250
end
4351

44-
context "when the string is a number with fractional part consisting of zeros" do
52+
context "when the string is a number with a trailing dot" do
53+
let(:str) { '123.' }
4554

55+
it "returns zero" do
56+
expect(actual).to eq(123)
57+
expect(actual).to be_a Integer
58+
end
59+
end
60+
61+
context "when the string is a number with fractional part consisting of zeros" do
4662
let(:str) { '12.000' }
4763

48-
it "returns the value as integer" do
64+
it "returns the value as an integer" do
4965
expect(actual).to eq(12)
66+
expect(actual).to be_a Integer
67+
end
68+
end
69+
70+
context "when the string is a number with leading dot then zeros" do
71+
let(:str) { '.000' }
72+
73+
it "returns the value as an integer" do
74+
expect(actual).to eq(0)
75+
expect(actual).to be_a Integer
76+
end
77+
end
78+
79+
context "when the string is non-numeric" do
80+
let(:str) { 'foo' }
81+
82+
it "raises ArgumentError" do
83+
expect { actual }.to raise_error(ArgumentError)
84+
end
85+
end
86+
87+
context "when the string is non-numeric with leading dot" do
88+
let(:str) { '.foo' }
89+
90+
it "raises ArgumentError" do
91+
expect { actual }.to raise_error(ArgumentError)
92+
end
93+
end
94+
95+
context "when the string is non-numeric with trailing dot" do
96+
let(:str) { 'foo.' }
97+
98+
it "raises ArgumentError" do
99+
expect { actual }.to raise_error(ArgumentError)
100+
end
101+
end
102+
103+
context "when the string is non-numeric with trailing dot and zeroes" do
104+
let(:str) { 'foo.000' }
105+
106+
it "raises ArgumentError" do
107+
expect { actual }.to raise_error(ArgumentError)
108+
end
109+
end
110+
111+
context "when the string is empty" do
112+
let(:str) { '' }
113+
114+
it "raises ArgumentError" do
115+
expect { actual }.to raise_error(ArgumentError)
50116
end
51117
end
52118
end

0 commit comments

Comments
 (0)