query_string_search 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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