query_string_search 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/query_string_search/abstract_comparison.rb +22 -24
- data/lib/query_string_search/abstract_matcher.rb +1 -1
- data/lib/query_string_search/comparison_factory.rb +8 -10
- data/lib/query_string_search/comparisons/inequality.rb +12 -14
- data/lib/query_string_search/comparisons/set.rb +13 -7
- data/lib/query_string_search/matchers/match_multiple_attribute_values.rb +0 -4
- data/lib/query_string_search/version.rb +1 -1
- data/spec/features/find_records_without_matching_attribute_values_spec.rb +30 -0
- data/spec/lib/query_string_search/comparisons/inequality_spec.rb +130 -0
- data/spec/lib/query_string_search/comparisons/set_spec.rb +46 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e26566e03c8bebf8eafc66136d2147f4aa5a84c7
|
4
|
+
data.tar.gz: 202bc4a25b3b21a6518659ed69a9e1482497ced7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a78fc8441f143d3e9190776df9e7882b8c082a1dc8ecd751b99575e1d0e1ffb96002026e273cd022d449accca4d4dbb7d38d7d9e15eb6f6cbd3833e510f7bb3d
|
7
|
+
data.tar.gz: dc593049a096450f40415d4935db92f27a4c5714ae2dcf4465c2ef15c353db1438d6836bf482188aa384ffa0a5c3ab030fc79e7a2757e8b281105bab5a8d12dc
|
data/README.md
CHANGED
@@ -24,6 +24,8 @@ Query String Example | What Data is Returned
|
|
24
24
|
`movies?q=rating=none` | Movies with a nil rating
|
25
25
|
`movies?q=year=1994` | Movies with a year of 1994
|
26
26
|
`movies?q=year=1994|1995` | Movies with a year of 1994 or 1995
|
27
|
+
`movies?q=year!1994` | Movies with a year that is not 1994
|
28
|
+
`movies?q=year!1994|1995` | Movies with a year that is not 1994 or 1995
|
27
29
|
`movies?q=title=Dunston%20Checks%20In` | Movies with the title Dunston Checks In
|
28
30
|
`movies?q=star_rating>1` | Movies with a star rating greater than one
|
29
31
|
`movies?q=star_rating<3` | Movies with a star rating less than three
|
@@ -31,6 +33,8 @@ Query String Example | What Data is Returned
|
|
31
33
|
`movies?q=star_rating<=4` | Movies with a star rating less than or equal to 4
|
32
34
|
`movies?q=home_formats=DVD` | Movies that are available on DVD.
|
33
35
|
`movies?q=home_formats=DVD|BD` | Movies that are available on DVD or Blu Ray
|
36
|
+
`movies?q=home_formats!DVD` | Movies that are not available on DVD.
|
37
|
+
`movies?q=home_formats!=DVD|BD` | Movies that are not available on DVD or Blu Ray
|
34
38
|
|
35
39
|
### Combining Searches
|
36
40
|
|
@@ -1,37 +1,35 @@
|
|
1
1
|
require "delegate"
|
2
2
|
|
3
3
|
module QueryStringSearch
|
4
|
-
|
5
|
-
|
6
|
-
attr_accessor :other, :subject, :operator
|
4
|
+
class AbstractComparison
|
5
|
+
attr_accessor :other, :subject, :operator
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def self.comparisons
|
8
|
+
descendants.push(self)
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def self.descendants
|
12
|
+
ObjectSpace.each_object(Class).select { |klass| klass < AbstractComparison }
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def self.all_reserved_operators
|
16
|
+
descendants.each_with_object([]) { |d, ret| ret << d.reserved_operators }.flatten
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def self.reserved_operators
|
20
|
+
[]
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def normalize(unnormalized)
|
24
|
+
Array(unnormalized).map(&:to_s).map(&:upcase)
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def compare
|
28
|
+
false
|
29
|
+
end
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
31
|
+
def self.build_me?(_)
|
32
|
+
true
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
@@ -1,15 +1,13 @@
|
|
1
1
|
module QueryStringSearch
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
comparison_to_build = available_comparisons.detect { |c| c.build_me?(matcher) }
|
2
|
+
class ComparisonFactory
|
3
|
+
def self.build(matcher, available_comparisons = AbstractComparison.comparisons)
|
4
|
+
comparison_to_build = available_comparisons.detect { |c| c.build_me?(matcher) }
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
6
|
+
if comparison_to_build
|
7
|
+
comparison = comparison_to_build.new
|
8
|
+
comparison.subject = matcher.desired_value
|
9
|
+
comparison.operator = matcher.operator
|
10
|
+
comparison
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
@@ -1,21 +1,19 @@
|
|
1
1
|
module QueryStringSearch
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
2
|
+
class InequalityComparison < AbstractComparison
|
3
|
+
def compare(other)
|
4
|
+
normalize(other).public_send(operator, normalize(subject))
|
5
|
+
end
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def normalize(unnormalized)
|
8
|
+
unnormalized.to_f
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def self.reserved_operators
|
12
|
+
[:<, :>, :<=, :>=]
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
15
|
+
def self.build_me?(matcher)
|
16
|
+
reserved_operators.include?(matcher.operator)
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
@@ -1,13 +1,19 @@
|
|
1
1
|
module QueryStringSearch
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
2
|
+
class SetComparison < AbstractComparison
|
3
|
+
def compare(other)
|
4
|
+
(normalize(subject) & normalize(other)).send(operator)
|
5
|
+
end
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
def operator=(x)
|
8
|
+
if x == :!=
|
9
|
+
super(:none?)
|
10
|
+
else
|
11
|
+
super(:any?)
|
10
12
|
end
|
11
13
|
end
|
14
|
+
|
15
|
+
def self.build_me?(matcher)
|
16
|
+
all_reserved_operators.none? { |o| o == matcher.operator }
|
17
|
+
end
|
12
18
|
end
|
13
19
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "../../lib/query_string_search"
|
2
|
+
require_relative "../fixtures/movie"
|
3
|
+
|
4
|
+
RSpec.describe "Finding data that does not have the requested value" do
|
5
|
+
let(:data_set) { Movie.random_collection }
|
6
|
+
|
7
|
+
it "Returns records that do not have a single value " do
|
8
|
+
expected_results = data_set.select { |d| d.year != "1994" }
|
9
|
+
actual_results = QueryStringSearch.new(data_set, "year!=1994").results
|
10
|
+
expect(actual_results).to eq(expected_results)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "Returns records that do not have a value in a collection " do
|
14
|
+
expected_results = data_set.select { |d| !d.home_formats.include?("BD") }
|
15
|
+
actual_results = QueryStringSearch.new(data_set, "home_formats!=BD").results
|
16
|
+
expect(actual_results).to eq(expected_results)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "Returns records that do not have any of the requested values " do
|
20
|
+
expected_results = data_set.select { |d| !%w(1994 1995).include?(d.year) }
|
21
|
+
actual_results = QueryStringSearch.new(data_set, "year!=1994|1995").results
|
22
|
+
expect(actual_results).to eq(expected_results)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "Returns records that do not have any of the requested values in their collection" do
|
26
|
+
expected_results = data_set.select { |d| !d.home_formats.include?("BD") && !d.home_formats.include?("DVD") }
|
27
|
+
actual_results = QueryStringSearch.new(data_set, "home_formats!=BD|DVD").results
|
28
|
+
expect(actual_results).to eq(expected_results)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require_relative "../../../../lib/query_string_search/abstract_comparison"
|
2
|
+
|
3
|
+
RSpec.describe QueryStringSearch::InequalityComparison do
|
4
|
+
describe "reserved_operators" do
|
5
|
+
it "reserves the equality comparison operators" do
|
6
|
+
expect([:<, :>, :<=, :>=]).to eq(QueryStringSearch::InequalityComparison.reserved_operators)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "build_me?" do
|
11
|
+
let(:matcher) { instance_double(QueryStringSearch::AbstractMatcher) }
|
12
|
+
it "is true if the matcher's operator is one of the Inequality reserved_operators" do
|
13
|
+
QueryStringSearch::InequalityComparison.reserved_operators.each do |o|
|
14
|
+
allow(matcher).to receive(:operator).and_return(o)
|
15
|
+
expect(QueryStringSearch::InequalityComparison.build_me?(matcher)).to be_truthy
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is false if the matcher's operator is not one of the reserved operators" do
|
20
|
+
allow(matcher).to receive(:operator).and_return(:inspect)
|
21
|
+
expect(QueryStringSearch::InequalityComparison.build_me?(matcher)).to be_falsey
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "compare" do
|
26
|
+
describe "using less than" do
|
27
|
+
let(:comparison) do
|
28
|
+
comparison = QueryStringSearch::InequalityComparison.new
|
29
|
+
comparison.subject = 1.0
|
30
|
+
comparison.operator = :<
|
31
|
+
comparison
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is true if the compared value is less than the subject" do
|
35
|
+
expect(comparison.compare(0.9)).to be_truthy
|
36
|
+
end
|
37
|
+
|
38
|
+
it "is false if the compared value is equal to the subject" do
|
39
|
+
expect(comparison.compare(1)).to be_falsey
|
40
|
+
end
|
41
|
+
|
42
|
+
it "is false if the compared value is greater than the subject" do
|
43
|
+
expect(comparison.compare(1.1)).to be_falsey
|
44
|
+
end
|
45
|
+
|
46
|
+
it "works if the values are strings" do
|
47
|
+
comparison.subject = "1.05"
|
48
|
+
expect(comparison.compare("1")).to be_truthy
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "using less-than-or-equal-to" do
|
54
|
+
let(:comparison) do
|
55
|
+
comparison = QueryStringSearch::InequalityComparison.new
|
56
|
+
comparison.subject = 1.0
|
57
|
+
comparison.operator = :<=
|
58
|
+
comparison
|
59
|
+
end
|
60
|
+
|
61
|
+
it "is true if the compared value is less than the subject" do
|
62
|
+
expect(comparison.compare(0.9)).to be_truthy
|
63
|
+
end
|
64
|
+
|
65
|
+
it "is true if the compared value is equal to the subject" do
|
66
|
+
expect(comparison.compare(1)).to be_truthy
|
67
|
+
end
|
68
|
+
|
69
|
+
it "is false if the compared value is greater than the subject" do
|
70
|
+
expect(comparison.compare(1.1)).to be_falsey
|
71
|
+
end
|
72
|
+
|
73
|
+
it "works if the values are strings" do
|
74
|
+
comparison.subject = "1.0"
|
75
|
+
expect(comparison.compare("1")).to be_truthy
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "greater than" do
|
80
|
+
let(:comparison) do
|
81
|
+
comparison = QueryStringSearch::InequalityComparison.new
|
82
|
+
comparison.subject = 1.0
|
83
|
+
comparison.operator = :>
|
84
|
+
comparison
|
85
|
+
end
|
86
|
+
|
87
|
+
it "is false if the compared value is less than the subject" do
|
88
|
+
expect(comparison.compare(0.9)).to be_falsey
|
89
|
+
end
|
90
|
+
|
91
|
+
it "is false if the compared value is equal to the subject" do
|
92
|
+
expect(comparison.compare(1)).to be_falsey
|
93
|
+
end
|
94
|
+
|
95
|
+
it "is true if the compared value is greater than the subject" do
|
96
|
+
expect(comparison.compare(1.1)).to be_truthy
|
97
|
+
end
|
98
|
+
|
99
|
+
it "works if the values are strings" do
|
100
|
+
comparison.subject = "1.0"
|
101
|
+
expect(comparison.compare("1.1")).to be_truthy
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "greater-than-or-equal-to" do
|
106
|
+
let(:comparison) do
|
107
|
+
comparison = QueryStringSearch::InequalityComparison.new
|
108
|
+
comparison.subject = 1.0
|
109
|
+
comparison.operator = :>=
|
110
|
+
comparison
|
111
|
+
end
|
112
|
+
|
113
|
+
it "is false if the compared value is less than the subject" do
|
114
|
+
expect(comparison.compare(0.9)).to be_falsey
|
115
|
+
end
|
116
|
+
|
117
|
+
it "is true if the compared value is equal to the subject" do
|
118
|
+
expect(comparison.compare(1)).to be_truthy
|
119
|
+
end
|
120
|
+
|
121
|
+
it "is true if the compared value is greater than the subject" do
|
122
|
+
expect(comparison.compare(1.1)).to be_truthy
|
123
|
+
end
|
124
|
+
|
125
|
+
it "works if the values are strings" do
|
126
|
+
comparison.subject = "1.0"
|
127
|
+
expect(comparison.compare("1")).to be_truthy
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative "../../../../lib/query_string_search/abstract_comparison"
|
2
|
+
|
3
|
+
RSpec.describe QueryStringSearch::SetComparison do
|
4
|
+
let(:value) { rand }
|
5
|
+
let(:comparison) do
|
6
|
+
c = QueryStringSearch::SetComparison.new
|
7
|
+
c.subject = value
|
8
|
+
c
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "comparing for existence" do
|
12
|
+
before do
|
13
|
+
comparison.operator = "=".to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "target has the data" do
|
17
|
+
it "returns true" do
|
18
|
+
expect(comparison.compare(value)).to be_truthy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "target does not have the data" do
|
23
|
+
it "returns true" do
|
24
|
+
expect(comparison.compare(value + 1)).to be_falsey
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "comparing for absence" do
|
30
|
+
before do
|
31
|
+
comparison.operator = :!=
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "target has the data" do
|
35
|
+
it "returns false" do
|
36
|
+
expect(comparison.compare(value)).to be_falsey
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "target does not have the data" do
|
41
|
+
it "returns true" do
|
42
|
+
expect(comparison.compare(value + 1)).to be_truthy
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: query_string_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Whitney
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-05-31 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -139,9 +139,12 @@ files:
|
|
139
139
|
- spec/features/find_records_with_matching_attribute_values_spec.rb
|
140
140
|
- spec/features/find_records_with_nil_attributes_spec.rb
|
141
141
|
- spec/features/find_records_with_nonnil_attributes_spec.rb
|
142
|
+
- spec/features/find_records_without_matching_attribute_values_spec.rb
|
142
143
|
- spec/features/find_seen_and_unseen_movies_spec.rb
|
143
144
|
- spec/fixtures/movie.rb
|
144
145
|
- spec/lib/query_string_search/abstract_matcher_spec.rb
|
146
|
+
- spec/lib/query_string_search/comparisons/inequality_spec.rb
|
147
|
+
- spec/lib/query_string_search/comparisons/set_spec.rb
|
145
148
|
- spec/lib/query_string_search/matcher_factory_spec.rb
|
146
149
|
- spec/lib/query_string_search/matchers/match_all_spec.rb
|
147
150
|
- spec/lib/query_string_search/matchers/match_attribute_spec.rb
|
@@ -186,9 +189,12 @@ test_files:
|
|
186
189
|
- spec/features/find_records_with_matching_attribute_values_spec.rb
|
187
190
|
- spec/features/find_records_with_nil_attributes_spec.rb
|
188
191
|
- spec/features/find_records_with_nonnil_attributes_spec.rb
|
192
|
+
- spec/features/find_records_without_matching_attribute_values_spec.rb
|
189
193
|
- spec/features/find_seen_and_unseen_movies_spec.rb
|
190
194
|
- spec/fixtures/movie.rb
|
191
195
|
- spec/lib/query_string_search/abstract_matcher_spec.rb
|
196
|
+
- spec/lib/query_string_search/comparisons/inequality_spec.rb
|
197
|
+
- spec/lib/query_string_search/comparisons/set_spec.rb
|
192
198
|
- spec/lib/query_string_search/matcher_factory_spec.rb
|
193
199
|
- spec/lib/query_string_search/matchers/match_all_spec.rb
|
194
200
|
- spec/lib/query_string_search/matchers/match_attribute_spec.rb
|