query_string_search 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d98152d90936269401df2e71217c03c41c5f249a
4
- data.tar.gz: b9d1b39ecfb46a0fbc15816e849575c30970e571
3
+ metadata.gz: 9ac9f7da9d9c53692c3ccb4e3c7fab60ba524d1f
4
+ data.tar.gz: 865d14548d4ed0aa2129b759f127b8b808d7121d
5
5
  SHA512:
6
- metadata.gz: 731af57376be5e8859edc378c5d2c3b6c41196ae88c4bda918ca0f973713fb5bfcc1a6f3d0844977deca202b278c74219341a48545bce9fc08250e9195e29bbf
7
- data.tar.gz: 4c1a8a92387aeb3390f4a46a0b40746b2dcc031b9586bbe0138dbce930e6360cb62d906f17b013006549580216bdf05e7d38b1f8267f0c37cd7d79c10ad48134
6
+ metadata.gz: 502464cf14160e106a69ccaa6b671db44650980c6db6e91acba6b5fe39f7e11aa28d70e1b04b0d657829ddf8c90df858aef79703e9f5c0148ea5478034f73407
7
+ data.tar.gz: fe7f411d65369fb73ec21f2cd15883149a47ae357fdb74d74eaf182f26c9988402f8ba5b453f7cbbe3032fe504842431a8aa12dfd3dbb217367ac41d6134264a
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  rvm:
3
4
  - 2.1.5
4
5
  - 2.2.0
data/README.md CHANGED
@@ -1,84 +1,59 @@
1
- # Query String Search [![Build Status](https://api.travis-ci.org/umn-asr/query_string_search.svg?branch=master)](https://travis-ci.org/umn-asr/query_string_search) [![Code Climate](https://codeclimate.com/github/umn-asr/query_string_search/badges/gpa.svg)](https://codeclimate.com/github/umn-asr/query_string_search)
1
+ # Query String Search
2
+ [![Build Status](https://api.travis-ci.org/umn-asr/query_string_search.svg?branch=master)](https://travis-ci.org/umn-asr/query_string_search)
3
+ [![Code Climate](https://codeclimate.com/github/umn-asr/query_string_search/badges/gpa.svg)](https://codeclimate.com/github/umn-asr/query_string_search)
4
+ [![Gem Version](https://badge.fury.io/rb/query_string_search.svg)](http://badge.fury.io/rb/query_string_search)
2
5
 
3
- Provides an easy way to implement searching in your API endpoints
6
+ Provides an easy way to implement searching in your API endpoints.
4
7
 
5
8
  ## Searches it supports
6
9
 
7
- Say you have a `movies` endpoint and people want to be able to search your huge collection of movie data. The API Search gem will give you the following search functionality:
8
-
9
- ### Return all data
10
-
11
- `movies` will return every movie in the data set.
12
-
13
- ### Return all data with non-null attribute value
14
-
15
- `movies?q=rating=all`
16
-
17
- Returns every movie with a non-nil rating.
18
-
19
- ### Return all data with null attribute value
20
-
21
- `movies?q=rating=none`
22
-
23
- Returns every movie without ratings.
24
-
25
- ### Return all data with an attribute value that matches
26
-
27
- `movies?q=year=1994`
28
-
29
- Returns every movie with a year of 1994
30
-
31
- ### Return all data that matches one of many attributes
32
-
33
- `movies?q=year=1994|1995`
34
-
35
- Returns all movies with a year of 1994 or 1995
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"
10
+ Say you have a `movies` endpoint and people want to be able to search your huge collection of movie data. Each of your movies have these properties
11
+
12
+ - Rating: returns "PG", "R", etc. Can also return nil
13
+ - Year: returns the year the film was released
14
+ - Title: The movie's title
15
+ - Star Rating: returns a number 1 to 5
16
+ - Home Formats: returns an array of available home formats. `["DVD", "BD"]`, for example.
17
+
18
+ The API Search gem will give you the following search functionality:
19
+
20
+ Query String Example | What Data is Returned
21
+ ------------- | -------------
22
+ `movies` | All data in your data set
23
+ `movies?q=rating=all` | Movies with a non-nil rating
24
+ `movies?q=rating=none` | Movies with a nil rating
25
+ `movies?q=year=1994` | Movies with a year of 1994
26
+ `movies?q=year=1994|1995` | Movies with a year of 1994 or 1995
27
+ `movies?q=title=Dunston%20Checks%20In` | Movies with the title Dunston Checks In
28
+ `movies?q=star_rating>1` | Movies with a star rating greater than one
29
+ `movies?q=star_rating<3` | Movies with a star rating less than three
30
+ `movies?q=star_rating>=2` | Movies with a star rating greater than or equal to 2
31
+ `movies?q=star_rating<=4` | Movies with a star rating less than or equal to 4
32
+ `movies?q=home_formats=DVD` | Movies that are available on DVD.
33
+ `movies?q=home_formats=DVD|BD` | Movies that are available on DVD or Blu Ray
62
34
 
63
35
  ### Combining Searches
64
36
 
65
- Search criteria can be separated with commas
37
+ Any of the above critera can be combined.
38
+ Just separate criteria with commas.
39
+ Records that match **all** the criteria will be returned.
40
+ Some examples!
66
41
 
67
- `movie?q=year=1994,country=US,rated=none`
42
+ `movie?q=year=1994,country=US,rated=none`<br />
43
+ All un-rated movies made in the US in 1994.
68
44
 
69
- Records that match **all** the criteria will be returned. All un-rated movies made in the US in 1994.
45
+ `movie?q=home_formats=BD|DVD,rated=R|PG,star_rating>3`<br />
46
+ All movies available on BD or DVD, that are rated R or PG, and that have a star rating greater than 3
70
47
 
71
- ## Installation
48
+ ## Use Cases
72
49
 
73
- Add this line to your application's Gemfile:
50
+ This gem fits best when you're trying to provide very flexible searching on a relatively small and flat set of data. Because it filters a data set that you provide, the speed at which it works is wholly dependent on the size of your data set.
74
51
 
75
- ```ruby
76
- gem 'query_string_search'
77
- ```
52
+ We currently use this gem on a small (~2000 rows) data set which is cached in memory. Response times using Rails/Passenger/Apache are always under 100ms, usually under 50ms. That's plenty fast! But if your initial data set is massive, or you can't cache it, your response times will be slower. Such is life. Gems like [Periscope](https://rubygems.org/gems/periscope) or [has_scope](https://rubygems.org/gems/has_scope) may be more your speed.
78
53
 
79
- And then execute:
54
+ A downside of gems like those, though, is that you end up defining all of your filtering methods in advance. This is not the case with Query String Search. If the elements in your data set respond to a method, then the data can be filtered by the return value of that method. It is possible that this is not what you want. In which case, check out those other gems. Or, you could also wrap your object instances in a wrapper that only responds to the methods that you want to filter on.
80
55
 
81
- $ bundle
56
+ Also, this gem is platform and persistence agnostic. Rails? Sinatra? Cuba? Redis? Postgres? Doesn't matter. You pass it objects, it filters them down based on the query string.
82
57
 
83
58
  ## Usage
84
59
 
@@ -90,20 +65,20 @@ Movie.all
90
65
 
91
66
  Or something similar. As long as it returns a collection of objects, you should be good.
92
67
 
93
- The objects must respond to the attributes you want to search on. Say you want to allow a search string like this:
68
+ The objects must respond to the methods you want to search on. Say you want to allow a search string like this:
94
69
 
95
- ```
96
70
  `movies?q=year=1994`
97
- ```
98
71
 
99
72
  Then every object in your data collection needs to respond to `year`.
100
73
 
101
- Again, with ActiveRecord this is pretty straightforward. But if you're building your data source from raw SQL then you're going to have to convert that data into objects that respond to the attributes you want to search on.
102
-
103
74
  Second, search! In Rails you can do something like this in a Controller method.
104
75
 
105
76
  ```ruby
106
- QueryStringSearch.new(data, query_string).results
77
+ def index
78
+ query_string = params[:q]
79
+ QueryStringSearch.new(Movie.all, query_string).results
80
+ #....
81
+ end
107
82
  ```
108
83
 
109
84
  This returns a collection of the objects that matched the search criteria.
@@ -111,12 +86,23 @@ This returns a collection of the objects that matched the search criteria.
111
86
  Or you can do it not in the controller. This will work:
112
87
 
113
88
  ```ruby
114
- test_query = "country=us"
115
- QueryStringSearch.new(Movie.all, test_query).results
89
+ QueryStringSearch.new(Movie.all, "country=us").results
116
90
  ```
117
91
 
118
92
  You get the idea. Pass in a data set and a query-stringish string and you'll get results back.
119
93
 
94
+ ## Installation
95
+
96
+ Add this line to your application's Gemfile:
97
+
98
+ ```ruby
99
+ gem 'query_string_search'
100
+ ```
101
+
102
+ And then execute:
103
+
104
+ $ bundle
105
+
120
106
 
121
107
  ## Contributing
122
108
 
@@ -1,6 +1,9 @@
1
1
  class MatchAttribute < QueryStringSearch::AbstractMatcher
2
2
  def match?(data)
3
- match_with_contingency { actual_value(data) }
3
+ match_with_contingency do
4
+ actual_value(data) == true ||
5
+ Array(actual_value(data)).any?
6
+ end
4
7
  end
5
8
 
6
9
  def self.reserved_words
@@ -1,6 +1,9 @@
1
1
  class MatchNoAttribute < QueryStringSearch::AbstractMatcher
2
2
  def match?(data)
3
- match_with_contingency { !actual_value(data) }
3
+ match_with_contingency do
4
+ actual_value(data) == false ||
5
+ Array(actual_value(data)).empty?
6
+ end
4
7
  end
5
8
 
6
9
  def self.reserved_words
@@ -1,3 +1,3 @@
1
1
  module QueryStringSearch
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -6,6 +6,8 @@ RSpec.describe "Finding data based on an attribute that returns a collection" do
6
6
 
7
7
  let(:movies_on_dvd) { data_set.select { |d| d.home_formats.include?("DVD") } }
8
8
  let(:movies_on_dvd_or_bd) { data_set.select { |d| d.home_formats.include?("DVD") || d.home_formats.include?("BD") } }
9
+ let(:movies_with_home_format) { data_set.select { |d| d.home_formats.any? } }
10
+ let(:movies_without_home_format) { data_set.select { |d| d.home_formats.none? } }
9
11
 
10
12
  it "Returns the correct records when searching for one value" do
11
13
  query_string = "home_formats=DVD"
@@ -20,4 +22,18 @@ RSpec.describe "Finding data based on an attribute that returns a collection" do
20
22
 
21
23
  expect(results).to eq(movies_on_dvd_or_bd)
22
24
  end
25
+
26
+ it "Returns the correct records when searching for all" do
27
+ query_string = "home_formats=#{ %w(all true).sample }"
28
+ results = QueryStringSearch.new(data_set, query_string).results
29
+
30
+ expect(results).to eq(movies_with_home_format)
31
+ end
32
+
33
+ it "Returns the correct records when searching for none" do
34
+ query_string = "home_formats=#{ %w(none false).sample }"
35
+ results = QueryStringSearch.new(data_set, query_string).results
36
+
37
+ expect(results).to eq(movies_without_home_format)
38
+ end
23
39
  end
@@ -16,7 +16,7 @@ class Movie
16
16
  self.country = random_country
17
17
  self.seen = [true, false].sample
18
18
  self.star_rating = [1, 2, 3, 4, 5].sample
19
- self.home_formats = %w(BD DVD Hulu Amazon Netflix).sample(2)
19
+ self.home_formats = %w(BD DVD Hulu Amazon Netflix).sample(rand(2))
20
20
  end
21
21
 
22
22
  def seen?
@@ -23,6 +23,16 @@ RSpec.describe MatchAttribute do
23
23
  end
24
24
  end
25
25
 
26
+ describe "if the target's attribute returns a collection" do
27
+ let(:target) { SearchTarget.new(property: %w(a b c)) }
28
+
29
+ it "is true" do
30
+ matcher = MatchAttribute.new
31
+ matcher.attribute = :property
32
+ expect(matcher.match?(target)).to be_truthy
33
+ end
34
+ end
35
+
26
36
  describe "if the target's attribute is nil" do
27
37
  let(:target) { SearchTarget.new(property: nil) }
28
38
 
@@ -36,7 +46,7 @@ RSpec.describe MatchAttribute do
36
46
  describe "if the target's attribute is false" do
37
47
  let(:target) { SearchTarget.new(property: false) }
38
48
 
39
- it "is true" do
49
+ it "is false" do
40
50
  matcher = MatchAttribute.new
41
51
  matcher.attribute = :property
42
52
  expect(matcher.match?(target)).to be_falsey
@@ -23,6 +23,16 @@ RSpec.describe MatchNoAttribute do
23
23
  end
24
24
  end
25
25
 
26
+ describe "if the target's attribute returns a collection" do
27
+ let(:target) { SearchTarget.new(property: %w(a b c)) }
28
+
29
+ it "is false" do
30
+ matcher = MatchNoAttribute.new
31
+ matcher.attribute = :property
32
+ expect(matcher.match?(target)).to be_falsey
33
+ end
34
+ end
35
+
26
36
  describe "if the target's attribute is false" do
27
37
  let(:target) { SearchTarget.new(property: false) }
28
38
 
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.5
4
+ version: 0.0.6
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-23 00:00:00.000000000 Z
13
+ date: 2015-04-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler