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

Fix MONGOID-4754 Some regular expressions are missing beginning/end anchors or are using them incorrectly #4645

Merged
merged 7 commits into from Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/mongoid/atomic/paths/embedded.rb
Expand Up @@ -21,7 +21,7 @@ module Embedded
#
# @since 2.1.0
def path
@path ||= position.sub(/\.\d+$/, "")
@path ||= position.sub(/\.\d+\z/, "")
end
end
end
Expand Down
22 changes: 7 additions & 15 deletions lib/mongoid/criteria/queryable/selector.rb
Expand Up @@ -22,9 +22,10 @@ def merge!(other)
other.each_pair do |key, value|
if value.is_a?(Hash) && self[key.to_s].is_a?(Hash)
value = self[key.to_s].merge(value) do |_key, old_val, new_val|
if in?(_key)
case _key
when '$in'
new_val & old_val
elsif nin?(_key)
when '$nin'
(old_val + new_val).uniq
else
new_val
Expand Down Expand Up @@ -179,10 +180,11 @@ def evolve_hash(serializer, value)
#
# @since 1.0.0
def multi_selection?(key)
key =~ /\$and|\$or|\$nor/
%w($and $or $nor).include?(key)
end

# Determines if the selection operator takes a list. Returns true for $in and $nin.
# Determines if the selection operator takes a list. Returns true for
# $in and $nin.
#
# @api private
#
Expand All @@ -195,17 +197,7 @@ def multi_selection?(key)
#
# @since 2.1.1
def multi_value?(key)
key =~ /\$nin|\$in/
end

private

def in?(key)
key =~ /\$in/
end

def nin?(key)
key =~ /\$nin/
%w($in $nin).include?(key)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/mongoid/extensions/string.rb
Expand Up @@ -77,7 +77,7 @@ def collectionize
#
# @since 2.3.1
def mongoid_id?
self =~ /\A(|_)id$/
self =~ /\A(|_)id\z/
end

# Is the string a number? The literals "NaN", "Infinity", and "-Infinity"
Expand All @@ -104,7 +104,7 @@ def numeric?
#
# @since 1.0.0
def reader
delete("=").sub(/\_before\_type\_cast$/, '')
delete("=").sub(/\_before\_type\_cast\z/, '')
end

# Is this string a writer?
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/positional.rb
Expand Up @@ -65,7 +65,7 @@ def replace_index(keys, position)
matches = position.scan(/\.\d+\./)
if matches.size == 1
keys.each do |kk|
if position =~ /^#{kk}\.\d+\.(.*)/
if position =~ /\A#{kk}\.\d+\.(.*)\z/
return "#{kk}.$.#{$1}"
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/query_cache.rb
Expand Up @@ -259,7 +259,7 @@ def cache_key
end

def system_collection?
collection.namespace =~ /^system./
collection.namespace =~ /\Asystem./
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/validatable/macros.rb
Expand Up @@ -49,7 +49,7 @@ def validates_uniqueness_of(*args)
# include Mongoid::Document
# field :title
#
# validates_format_of :title, with: /^[a-z0-9 \-_]*$/i
# validates_format_of :title, with: /\A[a-z0-9 \-_]*\z/i
# end
#
# @param [ Array ] args The names of the fields to validate.
Expand Down
54 changes: 54 additions & 0 deletions spec/mongoid/criteria/queryable/extensions/numeric_spec.rb
@@ -0,0 +1,54 @@
# frozen_string_literal: true
# encoding: utf-8

require "spec_helper"

describe Mongoid::Criteria::Queryable::Extensions::Numeric::ClassMethods do

let(:host) do
Class.new do
include Mongoid::Criteria::Queryable::Extensions::Numeric::ClassMethods
end.new
end

describe "#__numeric__" do

let(:actual) { host.__numeric__(str) }

context "when the string is a whole number" do

let(:str) { '123' }

it "returns the value as integer" do
expect(actual).to eq(123)
end
end

context "when the string is a floating point number" do

let(:str) { '123.45' }

it "returns the value as a float" do
expect(actual).to eq(123.45)
end
end

context "when the string is a dot only" do

let(:str) { '.' }

it "returns zero" do
expect(actual).to eq(0)
end
end

context "when the string is a number with fractional part consisting of zeros" do

let(:str) { '12.000' }

it "returns the value as integer" do
expect(actual).to eq(12)
end
end
end
end
68 changes: 68 additions & 0 deletions spec/mongoid/criteria/queryable/selector_spec.rb
Expand Up @@ -843,4 +843,72 @@ def localized?
end
end
end

describe '#multi_value?' do

let(:selector) do
described_class.new
end

context 'when key is $in' do
it 'returns true' do
expect(selector.send(:multi_value?, '$in')).to be true
end
end

context 'when key is $nin' do
it 'returns true' do
expect(selector.send(:multi_value?, '$nin')).to be true
end
end

context 'when key includes $in but is not $in' do
it 'returns false' do
expect(selector.send(:multi_value?, '$inc')).to be false
end
end

context 'when key is some other ey' do
it 'returns false' do
expect(selector.send(:multi_value?, 'foo')).to be false
end
end
end

describe '#multi_selection?' do

let(:selector) do
described_class.new
end

context 'when key is $and' do
it 'returns true' do
expect(selector.send(:multi_selection?, '$and')).to be true
end
end

context 'when key is $or' do
it 'returns true' do
expect(selector.send(:multi_selection?, '$or')).to be true
end
end

context 'when key is $nor' do
it 'returns true' do
expect(selector.send(:multi_selection?, '$nor')).to be true
end
end

context 'when key includes $or but is not $or' do
it 'returns false' do
expect(selector.send(:multi_selection?, '$ore')).to be false
end
end

context 'when key is some other ey' do
it 'returns false' do
expect(selector.send(:multi_selection?, 'foo')).to be false
end
end
end
end