query_string_search 0.0.4 → 0.0.5

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.md +26 -0
  4. data/lib/query_string_search.rb +6 -1
  5. data/lib/query_string_search/abstract_comparison.rb +38 -0
  6. data/lib/query_string_search/abstract_matcher.rb +15 -7
  7. data/lib/query_string_search/comparison_factory.rb +16 -0
  8. data/lib/query_string_search/comparisons/inequality.rb +21 -0
  9. data/lib/query_string_search/comparisons/set.rb +13 -0
  10. data/lib/query_string_search/matcher_factory.rb +8 -4
  11. data/lib/query_string_search/matchers/match_all.rb +2 -2
  12. data/lib/query_string_search/matchers/match_attribute.rb +4 -4
  13. data/lib/query_string_search/matchers/match_attribute_value.rb +6 -6
  14. data/lib/query_string_search/matchers/match_multiple_attribute_values.rb +10 -6
  15. data/lib/query_string_search/matchers/match_no_attribute.rb +4 -4
  16. data/lib/query_string_search/search_option.rb +35 -0
  17. data/lib/query_string_search/search_options.rb +4 -23
  18. data/lib/query_string_search/search_parameters.rb +5 -5
  19. data/lib/query_string_search/version.rb +1 -1
  20. data/spec/features/find_records_by_searching_a_attribute_that_returns_a_collection_spec.rb +23 -0
  21. data/spec/features/find_records_with_inequality_matchers_spec.rb +48 -0
  22. data/spec/fixtures/movie.rb +19 -15
  23. data/spec/lib/query_string_search/abstract_matcher_spec.rb +5 -2
  24. data/spec/lib/query_string_search/matcher_factory_spec.rb +11 -6
  25. data/spec/lib/query_string_search/matchers/match_all_spec.rb +22 -7
  26. data/spec/lib/query_string_search/matchers/match_attribute_spec.rb +25 -16
  27. data/spec/lib/query_string_search/matchers/match_attribute_value_spec.rb +38 -14
  28. data/spec/lib/query_string_search/matchers/match_multiple_attribute_values_spec.rb +22 -8
  29. data/spec/lib/query_string_search/matchers/match_no_attribute_spec.rb +25 -16
  30. data/spec/lib/query_string_search/search_option_spec.rb +34 -0
  31. data/spec/lib/query_string_search/search_options_spec.rb +19 -38
  32. metadata +13 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3b484ab328b2b5e889f3c0760ef857b3eccdddd8
4
- data.tar.gz: d0071f6f1ca439042d640ce53271beda186375e2
3
+ metadata.gz: d98152d90936269401df2e71217c03c41c5f249a
4
+ data.tar.gz: b9d1b39ecfb46a0fbc15816e849575c30970e571
5
5
  SHA512:
6
- metadata.gz: 44babe5feac2376030fe68edaa8a740c7f684959de01142558faa0d108ae86fc29ceeec5fd4a37896f38a19f6c95783c9da365afdea532632ab3e0ed110282f7
7
- data.tar.gz: bc97993d98ba3a8fd352729a2bbbb3a329ee1d28d957c926e210f311fd42670526b538834a423092bdac947b519d0d3e4c99849cf47886b30722b908025d1bb5
6
+ metadata.gz: 731af57376be5e8859edc378c5d2c3b6c41196ae88c4bda918ca0f973713fb5bfcc1a6f3d0844977deca202b278c74219341a48545bce9fc08250e9195e29bbf
7
+ data.tar.gz: 4c1a8a92387aeb3390f4a46a0b40746b2dcc031b9586bbe0138dbce930e6360cb62d906f17b013006549580216bdf05e7d38b1f8267f0c37cd7d79c10ad48134
@@ -6,4 +6,4 @@ rvm:
6
6
  addons:
7
7
  code_climate:
8
8
  repo_token:
9
- secure: XnZ8VLwsAVr3lrJ3gInolfi1dALfyu0XF74t7VExawsSGuDJzFnx4lwqw139uQHqEUNOl/lj+SHMjgEIxtoM6LjX/JBiCQLTMyKKz5EMwUvFULz4vWaGy2mgyA48WDXZL/s1k0GW7/Q8wxpdQ7uU2izx2RaJ+PLmcYUNQhNBbMI=
9
+ secure: xcf282dQMF1ZUZ9V9a/oY6zVo+nacSJqsxWJ7W8bOA4ii+Xq44EKLp1x88XSnWsD+yD3bdw4mHtPoQDCa+ouJLul5p35TwVZWGVxNdnWUdr3CjCS8lw4DYyR8BUHtH10JvvQN3AZpQ5IeHFqAujVMumfAPRkeuOLMs8iyfezrpI=
data/README.md CHANGED
@@ -34,6 +34,32 @@ Returns every movie with a year of 1994
34
34
 
35
35
  Returns all movies with a year of 1994 or 1995
36
36
 
37
+ ### Return all data with values greater than or less than an attribute
38
+
39
+ `movies?q=star_rating>1`
40
+ Returns all movies with a star rating greater than one
41
+
42
+ `movies?q=star_rating<3`
43
+ Returns all movies with a star rating less than three
44
+
45
+ `movies?q=star_rating>=2`
46
+ Returns all movies with a star rating greater than or equal to 2
47
+
48
+ `movies?q=star_rating<=4`
49
+ Returns all movies with a star rating less than or equal to 4
50
+
51
+ ### Search an attribute that returns a collection
52
+
53
+ If your `movie` has a `home_formats` method that retuns an array like `["DVD", "BD"]` you can filter that too.
54
+
55
+ `movies?q=home_formats=DVD`
56
+ Returns all movies whose `home_formats` includes "DVD"
57
+
58
+ or
59
+
60
+ `movies?q=home_formats=BD|DVD`
61
+ Returns all movies whose `home_formats` includes "DVD" or "BD"
62
+
37
63
  ### Combining Searches
38
64
 
39
65
  Search criteria can be separated with commas
@@ -4,7 +4,8 @@ module QueryStringSearch
4
4
  end
5
5
 
6
6
  class Search
7
- attr_accessor :data_source, :query_string
7
+ attr_accessor :data_source
8
+ attr_reader :query_string
8
9
 
9
10
  def initialize(data_source, query_string)
10
11
  self.data_source = data_source
@@ -21,6 +22,10 @@ module QueryStringSearch
21
22
 
22
23
  private
23
24
 
25
+ def query_string=(x)
26
+ @query_string = x ? CGI.unescape(x) : nil
27
+ end
28
+
24
29
  def filter_by_param(data, param)
25
30
  data.select { |c| param.match?(c) }
26
31
  end
@@ -0,0 +1,38 @@
1
+ require "delegate"
2
+
3
+ module QueryStringSearch
4
+ module Comparator
5
+ class AbstractComparison
6
+ attr_accessor :other, :subject, :operator
7
+
8
+ def self.comparisons
9
+ descendants.push(self)
10
+ end
11
+
12
+ def self.descendants
13
+ ObjectSpace.each_object(Class).select { |klass| klass < AbstractComparison }
14
+ end
15
+
16
+ def self.all_reserved_operators
17
+ descendants.each_with_object([]) { |d, ret| ret << d.reserved_operators }.flatten
18
+ end
19
+
20
+ def self.reserved_operators
21
+ []
22
+ end
23
+
24
+ def normalize(unnormalized)
25
+ Array(unnormalized).map(&:to_s).map(&:upcase)
26
+ end
27
+
28
+ def compare
29
+ false
30
+ end
31
+
32
+ def self.build_me?(_)
33
+ true
34
+ end
35
+ end
36
+ end
37
+ end
38
+ Dir.glob(File.join(File.dirname(__FILE__), "comparisons", "*.rb")) { |file| require file }
@@ -1,6 +1,7 @@
1
1
  module QueryStringSearch
2
2
  class AbstractMatcher
3
- attr_accessor :attribute, :value
3
+ attr_accessor :attribute, :desired_value
4
+ attr_reader :operator
4
5
 
5
6
  def self.matchers
6
7
  descendants.push(self)
@@ -14,11 +15,6 @@ module QueryStringSearch
14
15
  descendants.each_with_object([]) { |d, ret| ret << d.reserved_words }.flatten
15
16
  end
16
17
 
17
- def initialize(attribute = nil, value = nil)
18
- self.attribute = attribute
19
- self.value = value
20
- end
21
-
22
18
  def match?(_)
23
19
  false
24
20
  end
@@ -27,10 +23,18 @@ module QueryStringSearch
27
23
  []
28
24
  end
29
25
 
30
- def self.build_me?(_, _)
26
+ def self.build_me?(_)
31
27
  true
32
28
  end
33
29
 
30
+ def operator=(x)
31
+ @operator = x.to_s.to_sym
32
+ end
33
+
34
+ def comparison
35
+ @comparison ||= QueryStringSearch::Comparator::ComparisonFactory.build(self)
36
+ end
37
+
34
38
  private
35
39
 
36
40
  def match_with_contingency
@@ -38,6 +42,10 @@ module QueryStringSearch
38
42
  rescue
39
43
  false
40
44
  end
45
+
46
+ def actual_value(actual)
47
+ actual.public_send(attribute)
48
+ end
41
49
  end
42
50
  end
43
51
  Dir.glob(File.join(File.dirname(__FILE__), "matchers", "*.rb")) { |file| require file }
@@ -0,0 +1,16 @@
1
+ module QueryStringSearch
2
+ module Comparator
3
+ class ComparisonFactory
4
+ def self.build(matcher, available_comparisons = AbstractComparison.comparisons)
5
+ comparison_to_build = available_comparisons.detect { |c| c.build_me?(matcher) }
6
+
7
+ if comparison_to_build
8
+ comparison = comparison_to_build.new
9
+ comparison.subject = matcher.desired_value
10
+ comparison.operator = matcher.operator
11
+ comparison
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module QueryStringSearch
2
+ module Comparator
3
+ class Inequality < AbstractComparison
4
+ def compare(other)
5
+ normalize(other).public_send(operator, normalize(subject))
6
+ end
7
+
8
+ def normalize(unnormalized)
9
+ unnormalized.to_i
10
+ end
11
+
12
+ def self.reserved_operators
13
+ [:<, :>, :<=, :>=]
14
+ end
15
+
16
+ def self.build_me?(matcher)
17
+ reserved_operators.include?(matcher.operator)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module QueryStringSearch
2
+ module Comparator
3
+ class Set < AbstractComparison
4
+ def compare(other)
5
+ (normalize(subject) & normalize(other)).any?
6
+ end
7
+
8
+ def self.build_me?(matcher)
9
+ all_reserved_operators.none? { |o| o == matcher.operator }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,14 @@
1
1
  module QueryStringSearch
2
2
  class MatcherFactory
3
- def self.build(query_option, build_options)
4
- constructor = build_options.detect { |m| m.build_me?(query_option.search_type, query_option.search_param) }
3
+ def self.build(search_option, build_options)
4
+ matcher_to_build = build_options.detect { |m| m.build_me?(search_option) }
5
5
 
6
- if constructor
7
- constructor.new(query_option.search_type, query_option.search_param)
6
+ if matcher_to_build
7
+ matcher = matcher_to_build.new
8
+ matcher.attribute = search_option.attribute
9
+ matcher.desired_value = search_option.desired_value
10
+ matcher.operator = search_option.operator
11
+ matcher
8
12
  end
9
13
  end
10
14
  end
@@ -3,7 +3,7 @@ class MatchAll < QueryStringSearch::AbstractMatcher
3
3
  true
4
4
  end
5
5
 
6
- def self.build_me?(search_type, search_param)
7
- search_type.nil? && search_param.nil?
6
+ def self.build_me?(search_option)
7
+ search_option.attribute.nil? && search_option.desired_value.nil?
8
8
  end
9
9
  end
@@ -1,6 +1,6 @@
1
1
  class MatchAttribute < QueryStringSearch::AbstractMatcher
2
- def match?(target)
3
- match_with_contingency { target.public_send(attribute) }
2
+ def match?(data)
3
+ match_with_contingency { actual_value(data) }
4
4
  end
5
5
 
6
6
  def self.reserved_words
@@ -10,7 +10,7 @@ class MatchAttribute < QueryStringSearch::AbstractMatcher
10
10
  ]
11
11
  end
12
12
 
13
- def self.build_me?(_, search_param)
14
- reserved_words.any? { |r| r.match(search_param) }
13
+ def self.build_me?(search_option)
14
+ reserved_words.any? { |r| r.match(search_option.desired_value) }
15
15
  end
16
16
  end
@@ -1,13 +1,13 @@
1
1
  class MatchAttributeValue < QueryStringSearch::AbstractMatcher
2
- def match?(target)
2
+ def match?(data)
3
3
  match_with_contingency do
4
- target.public_send(attribute).to_s.upcase == value.to_s.upcase
4
+ comparison.compare(actual_value(data))
5
5
  end
6
6
  end
7
7
 
8
- def self.build_me?(search_type, search_param)
9
- search_param &&
10
- search_type &&
11
- all_reserved_words.none? { |r| r.match(search_param) }
8
+ def self.build_me?(search_option)
9
+ search_option.desired_value &&
10
+ search_option.attribute &&
11
+ all_reserved_words.none? { |r| r.match(search_option.desired_value) }
12
12
  end
13
13
  end
@@ -1,21 +1,25 @@
1
1
  class MatchMultipleAttributeValues < QueryStringSearch::AbstractMatcher
2
- def match?(target)
2
+ def match?(data)
3
3
  match_with_contingency do
4
- value.include?(target.public_send(attribute).to_s.upcase)
4
+ comparison.compare(actual_value(data))
5
5
  end
6
6
  end
7
7
 
8
+ def operator
9
+ :&
10
+ end
11
+
8
12
  def self.reserved_words
9
13
  [
10
14
  /^\w+\|\w+/
11
15
  ]
12
16
  end
13
17
 
14
- def value=(x)
15
- super(x.split("|").map(&:upcase))
18
+ def desired_value=(x)
19
+ super(x.split("|"))
16
20
  end
17
21
 
18
- def self.build_me?(_, search_param)
19
- reserved_words.any? { |r| r.match(search_param) }
22
+ def self.build_me?(search_option)
23
+ reserved_words.any? { |r| r.match(search_option.desired_value) }
20
24
  end
21
25
  end
@@ -1,6 +1,6 @@
1
1
  class MatchNoAttribute < QueryStringSearch::AbstractMatcher
2
- def match?(target)
3
- match_with_contingency { !target.public_send(attribute) }
2
+ def match?(data)
3
+ match_with_contingency { !actual_value(data) }
4
4
  end
5
5
 
6
6
  def self.reserved_words
@@ -10,7 +10,7 @@ class MatchNoAttribute < QueryStringSearch::AbstractMatcher
10
10
  ]
11
11
  end
12
12
 
13
- def self.build_me?(_, search_param)
14
- reserved_words.any? { |r| r.match(search_param) }
13
+ def self.build_me?(search_option)
14
+ reserved_words.any? { |r| r.match(search_option.desired_value) }
15
15
  end
16
16
  end
@@ -0,0 +1,35 @@
1
+ module QueryStringSearch
2
+ class SearchOption
3
+ attr_reader :attribute, :desired_value, :operator
4
+
5
+ def initialize(raw_query)
6
+ parsed_query = KeyValue.parse(raw_query)
7
+ self.attribute = parsed_query.attribute
8
+ self.desired_value = parsed_query.desired_value
9
+ self.operator = parsed_query.operator
10
+ end
11
+
12
+ def attribute
13
+ @attribute ? @attribute.to_sym : nil
14
+ end
15
+
16
+ private
17
+
18
+ attr_writer :attribute, :desired_value, :operator
19
+ end
20
+
21
+ class KeyValue
22
+ attr_accessor :attribute, :desired_value, :operator
23
+
24
+ def self.parse(raw_query)
25
+ new(/(?<attribute>\w+)(?<operator>\W+)(?<desired_value>.+)/.match(raw_query))
26
+ end
27
+
28
+ def initialize(match_data)
29
+ match_data = match_data ? match_data : {}
30
+ self.attribute = match_data[:attribute]
31
+ self.desired_value = match_data[:desired_value]
32
+ self.operator = match_data[:operator]
33
+ end
34
+ end
35
+ end
@@ -1,32 +1,13 @@
1
1
  module QueryStringSearch
2
- class SearchOptions
3
- attr_reader :search_type, :search_param
4
-
2
+ module SearchOptions
5
3
  def self.parse(query_string)
6
4
  if query_string
7
- search_params = query_string.split(",")
8
- search_params.each_with_object([]) do |p, ret|
9
- ret << new(p)
5
+ query_string.split(",").each_with_object([]) do |p, ret|
6
+ ret << QueryStringSearch::SearchOption.new(p)
10
7
  end
11
8
  else
12
- [new(nil)]
9
+ [QueryStringSearch::SearchOption.new(nil)]
13
10
  end
14
11
  end
15
-
16
- def initialize(raw_query)
17
- self.search_type, self.search_param = raw_query.to_s.split("=")
18
- end
19
-
20
- def search_type
21
- @search_type ? @search_type.to_sym : nil
22
- end
23
-
24
- def search_param
25
- @search_param ? CGI.unescape(@search_param) : @search_param
26
- end
27
-
28
- private
29
-
30
- attr_writer :search_type, :search_param
31
12
  end
32
13
  end
@@ -5,13 +5,13 @@ module QueryStringSearch
5
5
  def_delegators :@collection, :each
6
6
 
7
7
  def self.build_from_querystring(query_string, factory = QueryStringSearch::MatcherFactory, matchers = QueryStringSearch::AbstractMatcher.matchers)
8
- parameters = QueryStringSearch::SearchOptions.parse(query_string)
9
- new(parameters, factory, matchers)
8
+ search_options = QueryStringSearch::SearchOptions.parse(query_string)
9
+ new(search_options, factory, matchers)
10
10
  end
11
11
 
12
- def initialize(parameters, factory, matchers)
13
- parameters.each do |param|
14
- collection << factory.build(param, matchers)
12
+ def initialize(search_options, factory, matchers)
13
+ search_options.each do |search_option|
14
+ collection << factory.build(search_option, matchers)
15
15
  end
16
16
  end
17
17
 
@@ -1,3 +1,3 @@
1
1
  module QueryStringSearch
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,23 @@
1
+ require_relative "../../lib/query_string_search"
2
+ require_relative "../fixtures/movie"
3
+
4
+ RSpec.describe "Finding data based on an attribute that returns a collection" do
5
+ let(:data_set) { Movie.random_collection }
6
+
7
+ let(:movies_on_dvd) { data_set.select { |d| d.home_formats.include?("DVD") } }
8
+ let(:movies_on_dvd_or_bd) { data_set.select { |d| d.home_formats.include?("DVD") || d.home_formats.include?("BD") } }
9
+
10
+ it "Returns the correct records when searching for one value" do
11
+ query_string = "home_formats=DVD"
12
+ results = QueryStringSearch.new(data_set, query_string).results
13
+
14
+ expect(results).to eq(movies_on_dvd)
15
+ end
16
+
17
+ it "Returns the correct records when searching for two values" do
18
+ query_string = "home_formats=DVD|BD"
19
+ results = QueryStringSearch.new(data_set, query_string).results
20
+
21
+ expect(results).to eq(movies_on_dvd_or_bd)
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "../../lib/query_string_search"
2
+ require_relative "../fixtures/movie"
3
+
4
+ RSpec.describe "Finding data with inequality matchers" do
5
+ describe "Allows searching for values greater than a number" do
6
+ let(:data_set) { Movie.random_collection }
7
+ let(:movies_with_more_than_one_star) { data_set.select { |d| d.star_rating > 1 } }
8
+
9
+ it "Returns records that match the requested value" do
10
+ results = QueryStringSearch.new(data_set, "star_rating>1").results
11
+
12
+ expect(results).to eq(movies_with_more_than_one_star)
13
+ end
14
+ end
15
+
16
+ describe "Allows searching for values less than a number" do
17
+ let(:data_set) { Movie.random_collection }
18
+ let(:movies_with_fewer_than_three_stars) { data_set.select { |d| d.star_rating < 3 } }
19
+
20
+ it "Returns records that match the requested value" do
21
+ results = QueryStringSearch.new(data_set, "star_rating<3").results
22
+
23
+ expect(results).to eq(movies_with_fewer_than_three_stars)
24
+ end
25
+ end
26
+
27
+ describe "Allows searching for values greater than or equal to a number" do
28
+ let(:data_set) { Movie.random_collection }
29
+ let(:movies_with_two_or_more_stars) { data_set.select { |d| d.star_rating >= 2 } }
30
+
31
+ it "Returns records that match the requested value" do
32
+ results = QueryStringSearch.new(data_set, "star_rating>=2").results
33
+
34
+ expect(results).to eq(movies_with_two_or_more_stars)
35
+ end
36
+ end
37
+
38
+ describe "Allows searching for values less than or equal to a number" do
39
+ let(:data_set) { Movie.random_collection }
40
+ let(:movies_with_four_or_fewer_stars) { data_set.select { |d| d.star_rating <= 4 } }
41
+
42
+ it "Returns records that match the requested value" do
43
+ results = QueryStringSearch.new(data_set, "star_rating<=4").results
44
+
45
+ expect(results).to eq(movies_with_four_or_fewer_stars)
46
+ end
47
+ end
48
+ end
@@ -1,37 +1,41 @@
1
1
  class Movie
2
- attr_accessor :title, :rating, :year, :country, :seen
2
+ attr_accessor :title, :rating, :year, :country, :seen, :star_rating, :home_formats
3
3
 
4
- def self.random_collection(count = 1_000)
5
- (1...count).inject([]) do |collection, _|
6
- collection << Movie.new(random_title, random_rating, random_year, random_country)
7
- end
4
+ def self.random_collection(count = 100)
5
+ (1...count).map { |_| Movie.random }
8
6
  end
9
7
 
10
- def initialize(title, rating, year, country)
11
- self.title = title
12
- self.rating = rating
13
- self.year = year
14
- self.country = country
15
- self.seen = [true, false].sample
8
+ def self.random
9
+ Movie.new
10
+ end
11
+
12
+ def initialize
13
+ self.title = random_title
14
+ self.rating = random_rating
15
+ self.year = random_year
16
+ self.country = random_country
17
+ self.seen = [true, false].sample
18
+ self.star_rating = [1, 2, 3, 4, 5].sample
19
+ self.home_formats = %w(BD DVD Hulu Amazon Netflix).sample(2)
16
20
  end
17
21
 
18
22
  def seen?
19
23
  seen
20
24
  end
21
25
 
22
- def self.random_title
26
+ def random_title
23
27
  "Random Movie #{rand(10_000)}"
24
28
  end
25
29
 
26
- def self.random_rating
30
+ def random_rating
27
31
  ["X", "NC-17", "R", "PG-13", "PG", "G", nil].sample
28
32
  end
29
33
 
30
- def self.random_year
34
+ def random_year
31
35
  (1990..2014).to_a.sample.to_s
32
36
  end
33
37
 
34
- def self.random_country
38
+ def random_country
35
39
  %w(
36
40
  US CAN UK HK BR RUS FR IN
37
41
  ).sample
@@ -6,14 +6,17 @@ RSpec.describe QueryStringSearch::AbstractMatcher do
6
6
  it "is false" do
7
7
  value = rand
8
8
  target = OpenStruct.new(other: value)
9
- it = QueryStringSearch::AbstractMatcher.new(:other, value)
9
+ it = QueryStringSearch::AbstractMatcher.new
10
+ it.attribute = :other
11
+ it.desired_value = value
12
+ it.operator = "="
10
13
  expect(it.match?(target)).to be_falsey
11
14
  end
12
15
  end
13
16
 
14
17
  describe "build_me?" do
15
18
  it "is true" do
16
- it = QueryStringSearch::AbstractMatcher.build_me?(rand, rand)
19
+ it = QueryStringSearch::AbstractMatcher.build_me?(Object.new)
17
20
  expect(it).to be_truthy
18
21
  end
19
22
  end
@@ -7,16 +7,21 @@ RSpec.describe QueryStringSearch::MatcherFactory do
7
7
  let(:build_candidates) { [matcher_double] }
8
8
 
9
9
  before do
10
- allow(param_double).to receive(:search_param).and_return("test_search_param")
11
- allow(param_double).to receive(:search_type).and_return("test_search_type")
10
+ allow(param_double).to receive(:desired_value).and_return("test_search_value")
11
+ allow(param_double).to receive(:attribute).and_return("test_search_attribute")
12
+ allow(param_double).to receive(:operator).and_return("test_operator")
12
13
  end
13
14
 
14
15
  describe "build" do
15
16
  describe "finds a matcher to build" do
16
- it "builds that matcher and returns it" do
17
- test_return = Object.new
18
- expect(matcher_double).to receive(:build_me?).with(param_double.search_type, param_double.search_param).and_return(true)
19
- expect(matcher_double).to receive(:new).with(param_double.search_type, param_double.search_param).and_return(test_return)
17
+ it "builds that matcher, configures and returns it" do
18
+ test_return = instance_double(QueryStringSearch::AbstractMatcher.matchers.sample)
19
+ expect(test_return).to receive(:attribute=).with("test_search_attribute")
20
+ expect(test_return).to receive(:desired_value=).with("test_search_value")
21
+ expect(test_return).to receive(:operator=).with("test_operator")
22
+
23
+ expect(matcher_double).to receive(:build_me?).with(param_double).and_return(true)
24
+ expect(matcher_double).to receive(:new).and_return(test_return)
20
25
  expect(QueryStringSearch::MatcherFactory.build(param_double, build_candidates)).to eq(test_return)
21
26
  end
22
27
  end
@@ -3,23 +3,38 @@ require_relative "../../../../lib/query_string_search/abstract_matcher"
3
3
  RSpec.describe MatchAll do
4
4
  describe "match?" do
5
5
  it "is true" do
6
- it = MatchAll.new(:other, rand)
6
+ it = MatchAll.new
7
+ it.attribute = :other
8
+ it.desired_value = rand
7
9
  expect(it.match?(rand)).to be_truthy
8
10
  end
9
11
  end
10
12
 
11
13
  describe "build_me?" do
12
- describe "given a nil search_type and search_param" do
14
+ let(:search_option) { instance_double(QueryStringSearch::SearchOption) }
15
+
16
+ describe "given a nil attribute and desired_value" do
13
17
  it "is true" do
14
- expect(MatchAll.build_me?(nil, nil)).to be_truthy
18
+ allow(search_option).to receive(:attribute).and_return(nil)
19
+ allow(search_option).to receive(:desired_value).and_return(nil)
20
+
21
+ expect(MatchAll.build_me?(search_option)).to be_truthy
15
22
  end
16
23
  end
17
24
 
18
- describe "given a non-nil search_type or search_param" do
25
+ describe "given a non-nil attribute or desired_value" do
19
26
  it "is false" do
20
- expect(MatchAll.build_me?(rand, nil)).to be_falsey
21
- expect(MatchAll.build_me?(nil, rand)).to be_falsey
22
- expect(MatchAll.build_me?(rand, rand)).to be_falsey
27
+ allow(search_option).to receive(:attribute).and_return(rand)
28
+ allow(search_option).to receive(:desired_value).and_return(nil)
29
+ expect(MatchAll.build_me?(search_option)).to be_falsey
30
+
31
+ allow(search_option).to receive(:attribute).and_return(nil)
32
+ allow(search_option).to receive(:desired_value).and_return(rand)
33
+ expect(MatchAll.build_me?(search_option)).to be_falsey
34
+
35
+ allow(search_option).to receive(:attribute).and_return(rand)
36
+ allow(search_option).to receive(:desired_value).and_return(rand)
37
+ expect(MatchAll.build_me?(search_option)).to be_falsey
23
38
  end
24
39
  end
25
40
  end
@@ -5,63 +5,72 @@ RSpec.describe MatchAttribute do
5
5
  describe "match?" do
6
6
  describe "if the target's attribute is not nil" do
7
7
  let(:target) { SearchTarget.new(property: "search_value") }
8
- let(:subject) { MatchAttribute.new(:property) }
9
8
 
10
9
  it "is true" do
11
- expect(subject.match?(target)).to be_truthy
10
+ matcher = MatchAttribute.new
11
+ matcher.attribute = :property
12
+ expect(matcher.match?(target)).to be_truthy
12
13
  end
13
14
  end
14
15
 
15
16
  describe "if the target's attribute is true" do
16
17
  let(:target) { SearchTarget.new(property: true) }
17
- let(:subject) { MatchAttribute.new(:property) }
18
18
 
19
19
  it "is true" do
20
- expect(subject.match?(target)).to be_truthy
20
+ matcher = MatchAttribute.new
21
+ matcher.attribute = :property
22
+ expect(matcher.match?(target)).to be_truthy
21
23
  end
22
24
  end
23
25
 
24
26
  describe "if the target's attribute is nil" do
25
27
  let(:target) { SearchTarget.new(property: nil) }
26
- let(:subject) { MatchAttribute.new(:property) }
27
28
 
28
29
  it "is false" do
29
- expect(subject.match?(target)).to be_falsey
30
+ matcher = MatchAttribute.new
31
+ matcher.attribute = :property
32
+ expect(matcher.match?(target)).to be_falsey
30
33
  end
31
34
  end
32
35
 
33
36
  describe "if the target's attribute is false" do
34
37
  let(:target) { SearchTarget.new(property: false) }
35
- let(:subject) { MatchAttribute.new(:property) }
36
38
 
37
39
  it "is true" do
38
- expect(subject.match?(target)).to be_falsey
40
+ matcher = MatchAttribute.new
41
+ matcher.attribute = :property
42
+ expect(matcher.match?(target)).to be_falsey
39
43
  end
40
44
  end
41
45
 
42
46
  describe "if the target doesn't have the attribute" do
43
47
  let(:target) { SearchTarget.new(property: rand) }
44
- let(:subject) { MatchAttribute.new(:bad_attr) }
45
48
 
46
49
  it "is false" do
47
- expect(subject.match?(target)).to be_falsey
50
+ matcher = MatchAttribute.new
51
+ matcher.attribute = :bat_attr
52
+ expect(matcher.match?(target)).to be_falsey
48
53
  end
49
54
  end
50
55
  end
51
56
 
52
57
  describe "build_me?" do
53
- describe "given a search param of 'all' or 'true'" do
58
+ let(:search_option) { instance_double(QueryStringSearch::SearchOption) }
59
+
60
+ describe "given a value of 'all' or 'true'" do
54
61
  it "is true" do
55
- %w(all true).each do |search_param|
56
- expect(MatchAttribute.build_me?(rand, search_param)).to be_truthy
62
+ %w(all true).each do |desired_value|
63
+ allow(search_option).to receive(:desired_value).and_return(desired_value)
64
+ expect(MatchAttribute.build_me?(search_option)).to be_truthy
57
65
  end
58
66
  end
59
67
  end
60
68
 
61
- describe "given a search param that is not 'all' or 'true'" do
69
+ describe "given a value that is not 'all' or 'true'" do
62
70
  it "is false" do
63
- %w(1all rue).each do |search_param|
64
- expect(MatchAttribute.build_me?(rand, search_param)).to be_falsey
71
+ %w(1all rue).each do |desired_value|
72
+ allow(search_option).to receive(:desired_value).and_return(desired_value)
73
+ expect(MatchAttribute.build_me?(search_option)).to be_falsey
65
74
  end
66
75
  end
67
76
  end
@@ -5,53 +5,77 @@ RSpec.describe MatchAttributeValue do
5
5
  describe "match?" do
6
6
  describe "given a target with an attribute that matches the Parameter's attribute" do
7
7
  let(:target) { SearchTarget.new(property: "search_value") }
8
- let(:subject) { MatchAttributeValue.new(:property, "search_value") }
9
8
 
10
9
  it "returns true" do
11
- expect(subject.match?(target)).to be_truthy
10
+ matcher = MatchAttributeValue.new
11
+ matcher.attribute = :property
12
+ matcher.desired_value = "search_value"
13
+ matcher.operator = "="
14
+ expect(matcher.match?(target)).to be_truthy
12
15
  end
13
16
  end
14
17
 
15
18
  describe "given a value with spaces" do
16
19
  let(:target) { SearchTarget.new(property: "search value") }
17
- let(:subject) { MatchAttributeValue.new(:property, "search value") }
18
20
 
19
21
  it "returns true" do
20
- expect(subject.match?(target)).to be_truthy
22
+ matcher = MatchAttributeValue.new
23
+ matcher.attribute = :property
24
+ matcher.desired_value = "search value"
25
+ matcher.operator = "="
26
+ expect(matcher.match?(target)).to be_truthy
21
27
  end
22
28
  end
23
29
 
24
30
  describe "given a target with an attribute that does not match the Parameter's attribute" do
25
31
  let(:target) { SearchTarget.new(property: "other_value") }
26
- let(:subject) { MatchAttributeValue.new(:property, "search_value") }
27
32
 
28
33
  it "returns false" do
29
- expect(subject.match?(target)).to be_falsey
34
+ matcher = MatchAttributeValue.new
35
+ matcher.attribute = :property
36
+ matcher.desired_value = "search_value"
37
+ matcher.operator = "="
38
+ expect(matcher.match?(target)).to be_falsey
30
39
  end
31
40
  end
32
41
 
33
42
  describe "if the target doesn't have the attribute" do
34
43
  let(:target) { SearchTarget.new(property: "search_value") }
35
- let(:subject) { MatchAttribute.new(:bad_attr, "search_value") }
36
44
 
37
45
  it "is false" do
38
- expect(subject.match?(target)).to be_falsey
46
+ matcher = MatchAttributeValue.new
47
+ matcher.attribute = :bat_attr
48
+ matcher.desired_value = "search_value"
49
+ matcher.operator = "="
50
+ expect(matcher.match?(target)).to be_falsey
39
51
  end
40
52
  end
41
53
  end
42
54
 
43
55
  describe "build_me?" do
44
- describe "given a non-nil search_type and search_param" do
56
+ let(:search_option) { instance_double(QueryStringSearch::SearchOption) }
57
+
58
+ describe "given a non-nil attribute and desired_value" do
45
59
  it "is true" do
46
- expect(MatchAttributeValue.build_me?(rand.to_s, rand.to_s)).to be_truthy
60
+ allow(search_option).to receive(:attribute).and_return(rand.to_s)
61
+ allow(search_option).to receive(:desired_value).and_return(rand.to_s)
62
+ expect(MatchAttributeValue.build_me?(search_option)).to be_truthy
47
63
  end
48
64
  end
49
65
 
50
- describe "given a nil search_type or search_param" do
66
+ describe "given a nil attribute or desired_value" do
51
67
  it "is false" do
52
- expect(MatchAttributeValue.build_me?(rand.to_s, nil)).to be_falsey
53
- expect(MatchAttributeValue.build_me?(nil, rand.to_s)).to be_falsey
54
- expect(MatchAttributeValue.build_me?(nil, nil)).to be_falsey
68
+ allow(search_option).to receive(:attribute).and_return(rand.to_s)
69
+ allow(search_option).to receive(:desired_value).and_return(nil)
70
+ expect(MatchAttributeValue.build_me?(search_option)).to be_falsey
71
+
72
+ allow(search_option).to receive(:attribute).and_return(nil)
73
+ allow(search_option).to receive(:desired_value).and_return(rand.to_s)
74
+ expect(MatchAttributeValue.build_me?(search_option)).to be_falsey
75
+
76
+ allow(search_option).to receive(:attribute).and_return(nil)
77
+ allow(search_option).to receive(:desired_value).and_return(nil)
78
+ expect(MatchAttributeValue.build_me?(search_option)).to be_falsey
55
79
  end
56
80
  end
57
81
  end
@@ -5,20 +5,26 @@ RSpec.describe MatchMultipleAttributeValues do
5
5
  describe "match?" do
6
6
  it "matches if the target's attribute is one of the values" do
7
7
  target = SearchTarget.new(property: "1994")
8
- matcher = MatchMultipleAttributeValues.new(:property, "1994|1995")
8
+ matcher = MatchMultipleAttributeValues.new
9
+ matcher.attribute = :property
10
+ matcher.desired_value = "1994|1995"
9
11
  expect(matcher.match?(target)).to be_truthy
10
12
  end
11
13
 
12
14
  it "does not match if the target's attribute is not one of the values" do
13
15
  target = SearchTarget.new(property: "199")
14
- matcher = MatchMultipleAttributeValues.new(:property, "1994|1995")
16
+ matcher = MatchMultipleAttributeValues.new
17
+ matcher.attribute = :property
18
+ matcher.desired_value = "1994|1995"
15
19
  expect(matcher.match?(target)).to be_falsey
16
20
  end
17
21
 
18
22
  describe "if the target doesn't have the attribute" do
19
23
  it "is false" do
20
24
  target = SearchTarget.new(property: "1994")
21
- subject = MatchAttribute.new(:bad_attr, "1994|1995")
25
+ matcher = MatchMultipleAttributeValues.new
26
+ matcher.attribute = :bad_attr
27
+ matcher.desired_value = "1994|1995"
22
28
 
23
29
  expect(subject.match?(target)).to be_falsey
24
30
  end
@@ -26,21 +32,29 @@ RSpec.describe MatchMultipleAttributeValues do
26
32
  end
27
33
 
28
34
  describe "build_me?" do
29
- describe "given a search type and search param that contains a pipe" do
35
+ let(:search_option) { instance_double(QueryStringSearch::SearchOption) }
36
+
37
+ describe "given a search type and value that contains a pipe" do
30
38
  it "is true" do
31
- expect(MatchMultipleAttributeValues.build_me?(rand, "x|y")).to be_truthy
39
+ allow(search_option).to receive(:attribute).and_return(rand.to_s)
40
+ allow(search_option).to receive(:desired_value).and_return("x|y")
41
+ expect(MatchMultipleAttributeValues.build_me?(search_option)).to be_truthy
32
42
  end
33
43
  end
34
44
 
35
- describe "given a search type and search param that starts with a pipe" do
45
+ describe "given a search type and value that starts with a pipe" do
36
46
  it "is false" do
37
- expect(MatchMultipleAttributeValues.build_me?(rand, "|x|y")).to be_falsey
47
+ allow(search_option).to receive(:attribute).and_return(rand.to_s)
48
+ allow(search_option).to receive(:desired_value).and_return("|x|y")
49
+ expect(MatchMultipleAttributeValues.build_me?(search_option)).to be_falsey
38
50
  end
39
51
  end
40
52
 
41
53
  describe "given a search type without a pipe" do
42
54
  it "is false" do
43
- expect(MatchMultipleAttributeValues.build_me?(rand, "xy")).to be_falsey
55
+ allow(search_option).to receive(:attribute).and_return(rand.to_s)
56
+ allow(search_option).to receive(:desired_value).and_return("xy")
57
+ expect(MatchMultipleAttributeValues.build_me?(search_option)).to be_falsey
44
58
  end
45
59
  end
46
60
  end
@@ -5,63 +5,72 @@ RSpec.describe MatchNoAttribute do
5
5
  describe "match?" do
6
6
  describe "if the target's attribute is not nil" do
7
7
  let(:target) { SearchTarget.new(property: "search_value") }
8
- let(:subject) { MatchNoAttribute.new(:property) }
9
8
 
10
9
  it "is false" do
11
- expect(subject.match?(target)).to be_falsey
10
+ matcher = MatchNoAttribute.new
11
+ matcher.attribute = :property
12
+ expect(matcher.match?(target)).to be_falsey
12
13
  end
13
14
  end
14
15
 
15
16
  describe "if the target's attribute is true" do
16
17
  let(:target) { SearchTarget.new(property: true) }
17
- let(:subject) { MatchNoAttribute.new(:property) }
18
18
 
19
19
  it "is true" do
20
- expect(subject.match?(target)).to be_falsey
20
+ matcher = MatchNoAttribute.new
21
+ matcher.attribute = :property
22
+ expect(matcher.match?(target)).to be_falsey
21
23
  end
22
24
  end
23
25
 
24
26
  describe "if the target's attribute is false" do
25
27
  let(:target) { SearchTarget.new(property: false) }
26
- let(:subject) { MatchNoAttribute.new(:property) }
27
28
 
28
29
  it "is true" do
29
- expect(subject.match?(target)).to be_truthy
30
+ matcher = MatchNoAttribute.new
31
+ matcher.attribute = :property
32
+ expect(matcher.match?(target)).to be_truthy
30
33
  end
31
34
  end
32
35
 
33
36
  describe "if the target's attribute is nil" do
34
37
  let(:target) { SearchTarget.new(property: nil) }
35
- let(:subject) { MatchNoAttribute.new(:property) }
36
38
 
37
39
  it "is true" do
38
- expect(subject.match?(target)).to be_truthy
40
+ matcher = MatchNoAttribute.new
41
+ matcher.attribute = :property
42
+ expect(matcher.match?(target)).to be_truthy
39
43
  end
40
44
  end
41
45
 
42
46
  describe "if the target doesn't have the attribute" do
43
47
  let(:target) { SearchTarget.new(property: rand) }
44
- let(:subject) { MatchNoAttribute.new(:bad_attr) }
45
48
 
46
49
  it "is false" do
47
- expect(subject.match?(target)).to be_falsey
50
+ matcher = MatchNoAttribute.new
51
+ matcher.attribute = :bad_attr
52
+ expect(matcher.match?(target)).to be_falsey
48
53
  end
49
54
  end
50
55
  end
51
56
 
52
57
  describe "build_me?" do
53
- describe "given a search param of 'none' or 'false'" do
58
+ let(:search_option) { instance_double(QueryStringSearch::SearchOption) }
59
+
60
+ describe "given a value of 'none' or 'false'" do
54
61
  it "is true" do
55
- %w(none false).each do |search_param|
56
- expect(MatchNoAttribute.build_me?(rand, search_param)).to be_truthy
62
+ %w(none false).each do |desired_value|
63
+ allow(search_option).to receive(:desired_value).and_return(desired_value)
64
+ expect(MatchNoAttribute.build_me?(search_option)).to be_truthy
57
65
  end
58
66
  end
59
67
  end
60
68
 
61
- describe "given a search param that is not 'none' or 'false'" do
69
+ describe "given a value that is not 'none' or 'false'" do
62
70
  it "is false" do
63
- %w(one falsey).each do |search_param|
64
- expect(MatchNoAttribute.build_me?(rand, search_param)).to be_falsey
71
+ %w(one falsey).each do |desired_value|
72
+ allow(search_option).to receive(:desired_value).and_return(desired_value)
73
+ expect(MatchNoAttribute.build_me?(search_option)).to be_falsey
65
74
  end
66
75
  end
67
76
  end
@@ -0,0 +1,34 @@
1
+ require_relative "../../../lib/query_string_search/search_option"
2
+
3
+ RSpec.describe QueryStringSearch::SearchOption do
4
+ describe "new" do
5
+ describe "with equality operator" do
6
+ let(:equal_query) { "test=2" }
7
+
8
+ it "correctly splits the attribute, value and operator" do
9
+ equal_option = QueryStringSearch::SearchOption.new("test=2")
10
+ expect(equal_option.attribute).to eq(:test)
11
+ expect(equal_option.desired_value).to eq("2")
12
+ expect(equal_option.operator).to eq("=")
13
+ end
14
+ end
15
+
16
+ describe "with inequality operators" do
17
+ let(:less_than_query_string) { "test<1" }
18
+ let(:greater_than_or_equal_query) { "test>=2" }
19
+
20
+ it "correctly splits the attribute, value and operator" do
21
+ less_than = QueryStringSearch::SearchOption.new(less_than_query_string)
22
+ greater_or_equal = QueryStringSearch::SearchOption.new(greater_than_or_equal_query)
23
+
24
+ expect(less_than.attribute).to eq(:test)
25
+ expect(less_than.desired_value).to eq("1")
26
+ expect(less_than.operator).to eq("<")
27
+
28
+ expect(greater_or_equal.attribute).to eq(:test)
29
+ expect(greater_or_equal.desired_value).to eq("2")
30
+ expect(greater_or_equal.operator).to eq(">=")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -2,51 +2,32 @@ require_relative "../../../lib/query_string_search/search_options"
2
2
 
3
3
  RSpec.describe QueryStringSearch::SearchOptions do
4
4
  describe "parse" do
5
- describe "with a single-element and multi-element query_string" do
6
- let(:single_query_string) { "test=filter" }
7
- let(:multi_query_string) { "test=filter,test2=test%20attribute" }
8
- let(:single_element) { QueryStringSearch::SearchOptions.parse(single_query_string) }
9
- let(:multi_element) { QueryStringSearch::SearchOptions.parse(multi_query_string) }
10
-
11
- describe "returns a collection" do
12
- it "that is enumerable" do
13
- [single_element, multi_element].each do |it|
14
- expect(it).to respond_to(:each)
15
- end
16
- end
17
-
18
- describe "whose contents" do
19
- it "have search_type that are symbols" do
20
- expect(single_element.collect(&:search_type)).to eq([:test])
21
- expect(multi_element.collect(&:search_type)).to eq([:test, :test2])
22
- end
5
+ describe "with a single-element query_string" do
6
+ it "returns a collection of a single search option" do
7
+ option_double = Object.new
8
+ expect(QueryStringSearch::SearchOption).to receive(:new).with("test=filter").and_return(option_double)
9
+ expect(QueryStringSearch::SearchOptions.parse("test=filter")).to eq([option_double])
10
+ end
11
+ end
23
12
 
24
- it "have search_param that are unescaped strings" do
25
- expect(single_element.collect(&:search_param)).to eq(["filter"])
26
- expect(multi_element.collect(&:search_param)).to eq(["filter", "test attribute"])
27
- end
28
- end
13
+ describe "with a multi-element query_string" do
14
+ let(:multi_query_string) { "test=filter,test2=test attribute" }
15
+ it "returns a collection of a multiple search options" do
16
+ option_double1 = Object.new
17
+ option_double2 = Object.new
18
+ expect(QueryStringSearch::SearchOption).to receive(:new).with("test=filter").and_return(option_double1)
19
+ expect(QueryStringSearch::SearchOption).to receive(:new).with("test2=test attribute").and_return(option_double2)
20
+ expect(QueryStringSearch::SearchOptions.parse(multi_query_string)).to eq([option_double1, option_double2])
29
21
  end
30
22
  end
31
23
 
32
24
  describe "with a nil" do
33
25
  let(:nil_element) { QueryStringSearch::SearchOptions.parse(nil) }
34
- describe "returns a collection" do
35
- it "that is enumerable" do
36
- expect(nil_element).to respond_to(:each)
37
- end
38
-
39
- it "with one element" do
40
- expect(nil_element.count).to eq(1)
41
- end
42
-
43
- it "with nil search_type" do
44
- expect(nil_element.first.search_type).to be_nil
45
- end
26
+ it "creates a collection with one nil search option" do
27
+ option_double = Object.new
28
+ expect(QueryStringSearch::SearchOption).to receive(:new).with(nil).and_return(option_double)
46
29
 
47
- it "with nil search_param" do
48
- expect(nil_element.first.search_param).to be_nil
49
- end
30
+ expect(QueryStringSearch::SearchOptions.parse(nil)).to eq([option_double])
50
31
  end
51
32
  end
52
33
  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
4
+ version: 0.0.5
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-02-11 00:00:00.000000000 Z
13
+ date: 2015-02-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -114,21 +114,28 @@ files:
114
114
  - README.md
115
115
  - Rakefile
116
116
  - lib/query_string_search.rb
117
+ - lib/query_string_search/abstract_comparison.rb
117
118
  - lib/query_string_search/abstract_matcher.rb
119
+ - lib/query_string_search/comparison_factory.rb
120
+ - lib/query_string_search/comparisons/inequality.rb
121
+ - lib/query_string_search/comparisons/set.rb
118
122
  - lib/query_string_search/matcher_factory.rb
119
123
  - lib/query_string_search/matchers/match_all.rb
120
124
  - lib/query_string_search/matchers/match_attribute.rb
121
125
  - lib/query_string_search/matchers/match_attribute_value.rb
122
126
  - lib/query_string_search/matchers/match_multiple_attribute_values.rb
123
127
  - lib/query_string_search/matchers/match_no_attribute.rb
128
+ - lib/query_string_search/search_option.rb
124
129
  - lib/query_string_search/search_options.rb
125
130
  - lib/query_string_search/search_parameters.rb
126
131
  - lib/query_string_search/version.rb
127
132
  - query_string_search.gemspec
128
133
  - spec/doubles/search_target.rb
129
134
  - spec/features/find_all_data_spec.rb
135
+ - spec/features/find_records_by_searching_a_attribute_that_returns_a_collection_spec.rb
130
136
  - spec/features/find_records_that_match_multiple_parameters_spec.rb
131
137
  - spec/features/find_records_that_match_one_of_many_attributes_spec.rb
138
+ - spec/features/find_records_with_inequality_matchers_spec.rb
132
139
  - spec/features/find_records_with_matching_attribute_values_spec.rb
133
140
  - spec/features/find_records_with_nil_attributes_spec.rb
134
141
  - spec/features/find_records_with_nonnil_attributes_spec.rb
@@ -141,6 +148,7 @@ files:
141
148
  - spec/lib/query_string_search/matchers/match_attribute_value_spec.rb
142
149
  - spec/lib/query_string_search/matchers/match_multiple_attribute_values_spec.rb
143
150
  - spec/lib/query_string_search/matchers/match_no_attribute_spec.rb
151
+ - spec/lib/query_string_search/search_option_spec.rb
144
152
  - spec/lib/query_string_search/search_options_spec.rb
145
153
  - spec/lib/query_string_search/search_parameters_spec.rb
146
154
  - spec/spec_helper.rb
@@ -171,8 +179,10 @@ summary: Provides a standard way to do searches using query strings in an API en
171
179
  test_files:
172
180
  - spec/doubles/search_target.rb
173
181
  - spec/features/find_all_data_spec.rb
182
+ - spec/features/find_records_by_searching_a_attribute_that_returns_a_collection_spec.rb
174
183
  - spec/features/find_records_that_match_multiple_parameters_spec.rb
175
184
  - spec/features/find_records_that_match_one_of_many_attributes_spec.rb
185
+ - spec/features/find_records_with_inequality_matchers_spec.rb
176
186
  - spec/features/find_records_with_matching_attribute_values_spec.rb
177
187
  - spec/features/find_records_with_nil_attributes_spec.rb
178
188
  - spec/features/find_records_with_nonnil_attributes_spec.rb
@@ -185,6 +195,7 @@ test_files:
185
195
  - spec/lib/query_string_search/matchers/match_attribute_value_spec.rb
186
196
  - spec/lib/query_string_search/matchers/match_multiple_attribute_values_spec.rb
187
197
  - spec/lib/query_string_search/matchers/match_no_attribute_spec.rb
198
+ - spec/lib/query_string_search/search_option_spec.rb
188
199
  - spec/lib/query_string_search/search_options_spec.rb
189
200
  - spec/lib/query_string_search/search_parameters_spec.rb
190
201
  - spec/spec_helper.rb