mundane-search 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +110 -7
- data/lib/mundane-search/filters/order.rb +35 -0
- data/lib/mundane-search/filters/typical.rb +3 -2
- data/lib/mundane-search/result_model.rb +6 -0
- data/lib/mundane-search/version.rb +1 -1
- data/lib/mundane-search/view_helpers.rb +6 -0
- data/spec/filters/order_integration_spec.rb +24 -0
- data/spec/filters/order_spec.rb +28 -0
- data/spec/filters/typical_spec.rb +4 -0
- data/spec/minitest_helper.rb +14 -0
- data/spec/search_url_for_integration_spec.rb +20 -0
- metadata +12 -5
data/README.md
CHANGED
@@ -12,9 +12,7 @@ You know the deal:
|
|
12
12
|
|
13
13
|
## Usage
|
14
14
|
|
15
|
-
Still in the process of figuring this out! But much of it works like I want, so hopefully no brutal changes
|
16
|
-
|
17
|
-
### Typical use
|
15
|
+
*Still in the process of figuring this out! But much of it works like I want, so hopefully no brutal changes.*
|
18
16
|
|
19
17
|
Build a search, then run that search on a specific collection and params.
|
20
18
|
|
@@ -30,25 +28,130 @@ Create a search:
|
|
30
28
|
Add filters to it:
|
31
29
|
|
32
30
|
class BookSearch < MundaneSearch::Result
|
33
|
-
use
|
31
|
+
use :attribute_match, param_key: "title"
|
34
32
|
end
|
35
33
|
|
36
34
|
Then use that search in your controllers:
|
37
35
|
|
38
|
-
# params = { "title" => "A Tale of Two Cities" }
|
39
|
-
@result = BookSearch.results_for(Book.scoped, params)
|
36
|
+
# params = { "book_search" => { "title" => "A Tale of Two Cities" } }
|
37
|
+
@result = BookSearch.results_for(Book.scoped, params["book_search"])
|
40
38
|
|
41
39
|
The returned result is enumerable:
|
42
40
|
|
43
41
|
@result.each {|book| ... }
|
44
42
|
@result.first
|
45
43
|
|
46
|
-
And has some Rails form compatibility:
|
44
|
+
And has some Rails-style form compatibility:
|
47
45
|
|
48
46
|
<%= search_form_for(@result) do |f| %>
|
49
47
|
<%= f.input :title %>
|
50
48
|
<% end %>
|
51
49
|
|
50
|
+
As well as url-ability:
|
51
|
+
|
52
|
+
search_url_for(@result)
|
53
|
+
|
54
|
+
## Filters
|
55
|
+
|
56
|
+
There are built in filters and you can make your own filters.
|
57
|
+
|
58
|
+
Three ways to notate filters:
|
59
|
+
|
60
|
+
class ExampleSearch < MundaneSearch::Result
|
61
|
+
use FilterClass
|
62
|
+
use :filter_class
|
63
|
+
employ :shortcut
|
64
|
+
end
|
65
|
+
|
66
|
+
1. use FilterClass, options
|
67
|
+
The most straightforward. Under the hood, this establishes that a searched collection will be
|
68
|
+
passed through this filter.
|
69
|
+
2. use :filter_class, options
|
70
|
+
This is the same as specifying FilterClass, except MundaneSearch will look for filter_class
|
71
|
+
in MundaneSearch::Filters if it isn't found in the Object namespace.
|
72
|
+
3. employ :shortcut, options
|
73
|
+
This is the avenue for shortcuts, such as when you might want several filters to be created
|
74
|
+
by one designation.
|
75
|
+
I haven't spent much thought on this, it may change in the future.
|
76
|
+
|
77
|
+
|
78
|
+
## Built in filters
|
79
|
+
|
80
|
+
### Common options
|
81
|
+
|
82
|
+
First some options that are common to many filters.
|
83
|
+
|
84
|
+
* param_key: The key in params to examine for a matching value.
|
85
|
+
* target: The attribute to match against. By default, uses param_key.
|
86
|
+
* match_value: Usually nil. When nil, the value of params[param_key] is used.
|
87
|
+
* required: Default false. When true, will run a filter even if (for example) the match_value is nil.
|
88
|
+
* type: Gives form helpers et al a hint as to what type the match_value should be. Overrides class method param_key_type in a filter.
|
89
|
+
Available types:
|
90
|
+
1. :string
|
91
|
+
2. :integer
|
92
|
+
3. :float
|
93
|
+
4. :date
|
94
|
+
5. :time
|
95
|
+
|
96
|
+
All those suckers in action:
|
97
|
+
|
98
|
+
class BookSearch < MundaneSearch::Result
|
99
|
+
# book.publisher == params["publisher"] even if the match_value (params["publisher"]) is nil
|
100
|
+
# (in below examples, the filter is skipped if the match_value is nil)
|
101
|
+
use :attribute_match, param_key: "publisher", required: true
|
102
|
+
|
103
|
+
# book.title == params["title"]
|
104
|
+
use :attribute_match, param_key: "title"
|
105
|
+
|
106
|
+
# book.author == params["writer"]
|
107
|
+
use :attribute_match, param_key: "writer", target: "author"
|
108
|
+
|
109
|
+
# book.publication_date > Date.parse("1900-01-01") (disregards params)
|
110
|
+
use :operator, param_key: "publication_date", operator: :>, match_value: Date.parse("1900-01-01")
|
111
|
+
|
112
|
+
# simple_form displays filter as designated type
|
113
|
+
use :attribute_match, param_key: "first_purchased_at", type: :time
|
114
|
+
end
|
115
|
+
|
116
|
+
### AttributeMatch
|
117
|
+
|
118
|
+
Returns objects that exactly match an attribute, ex: book.title == "A Tale of Two Cities"
|
119
|
+
|
120
|
+
use :attribute_match, param_key: "title"
|
121
|
+
|
122
|
+
### AttributeSubstring
|
123
|
+
|
124
|
+
Returns objects that match a portion of an attribute, ex: book.title =~ /Tale of/
|
125
|
+
|
126
|
+
use :attribute_substring, param_key: title
|
127
|
+
|
128
|
+
### Operator
|
129
|
+
|
130
|
+
Returns objects that match an attribute + operator, ex: book.publication_date > Date.parse("1900-01-01")
|
131
|
+
|
132
|
+
Requires a param_key and a symbol of an operator (:>, :<, :>=, :<=)
|
133
|
+
|
134
|
+
use :operator, param_key: "publication_date", operator: :>
|
135
|
+
|
136
|
+
### Order
|
137
|
+
|
138
|
+
Sorts a collection.
|
139
|
+
|
140
|
+
use :order, param_key: "sort", direction: "asc"
|
141
|
+
|
142
|
+
|
143
|
+
#### ExactMatch
|
144
|
+
|
145
|
+
MundaneSearch can also work with objects that aren't "attribute-y".
|
146
|
+
|
147
|
+
Return objects that are equal to the match_value. Used in a lot of examples below.
|
148
|
+
|
149
|
+
### BlankParamsAreNil
|
150
|
+
|
151
|
+
The params can be manipulated.
|
152
|
+
|
153
|
+
Changes values of "", [], or {} to nil in params.
|
154
|
+
|
52
155
|
## Sans sugar
|
53
156
|
|
54
157
|
MundaneSearch can be used outside of Rails on whatever sort of object you want:
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module MundaneSearch::Filters
|
2
|
+
class Order < Typical
|
3
|
+
class ActiveRecord < self
|
4
|
+
def filtered_collection
|
5
|
+
collection.order("#{match_value} #{active_record_direction}")
|
6
|
+
end
|
7
|
+
|
8
|
+
def active_record_direction
|
9
|
+
direction || "ASC"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def filtered_collection
|
14
|
+
collection.sort_by(&:"#{match_value}")
|
15
|
+
backwards? ? collection.reverse : collection
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
def backwards?
|
20
|
+
descending_terms.include?(direction)
|
21
|
+
end
|
22
|
+
|
23
|
+
def direction
|
24
|
+
params["direction"] || options[:direction]
|
25
|
+
end
|
26
|
+
|
27
|
+
def ascending_terms
|
28
|
+
%w(asc ascending <)
|
29
|
+
end
|
30
|
+
|
31
|
+
def descending_terms
|
32
|
+
%w(desc descending >)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -21,11 +21,12 @@ module MundaneSearch::Filters
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def match_value
|
24
|
-
params[param_key]
|
24
|
+
options[:match_value] || params[param_key]
|
25
25
|
end
|
26
26
|
|
27
|
+
# This is a duplicate of the class method?
|
27
28
|
def param_key_type
|
28
|
-
options[:type] ||
|
29
|
+
options[:type] || self.class.param_key_type
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -22,6 +22,12 @@ module MundaneSearch
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
# Added this for the benefit of search_url_for
|
26
|
+
# If it stays, it should replace stack.params in the method above.
|
27
|
+
def params
|
28
|
+
send(:result).stack.params
|
29
|
+
end
|
30
|
+
|
25
31
|
def self.model_name
|
26
32
|
name = 'GenericSearch' unless self.name
|
27
33
|
namespace = nil
|
@@ -1,5 +1,11 @@
|
|
1
1
|
module MundaneSearch
|
2
2
|
module ViewHelpers
|
3
|
+
def search_url_for(search, change_params = {})
|
4
|
+
search_model = search.to_model
|
5
|
+
new_parms = search_model.params.merge(change_params).reject {|k,v| v.nil? }
|
6
|
+
polymorphic_url search_model, new_parms
|
7
|
+
end
|
8
|
+
|
3
9
|
def search_form_for(record, options = {}, &block)
|
4
10
|
# Later!
|
5
11
|
# if block_given?
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../minitest_helper'
|
2
|
+
require_relative '../active_record_setup'
|
3
|
+
|
4
|
+
describe MundaneSearch::Filters::Order do
|
5
|
+
before do
|
6
|
+
DatabaseCleaner.clean
|
7
|
+
populate_books!
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:all_books) { Book.scoped }
|
11
|
+
let(:a_tale_of_two_cities) { Book.first }
|
12
|
+
|
13
|
+
it "should match based on param_key" do
|
14
|
+
built = MundaneSearch::Builder.new do
|
15
|
+
use MundaneSearch::Filters::Order, param_key: "sort"
|
16
|
+
end
|
17
|
+
|
18
|
+
dates = built.call(all_books, {"sort" => "publication_date"})
|
19
|
+
dates.inject do |last, current|
|
20
|
+
last.publication_date.must_be :<, current.publication_date if last
|
21
|
+
current
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative '../minitest_helper'
|
2
|
+
require_relative '../demo_data'
|
3
|
+
|
4
|
+
describe MundaneSearch::Filters::Order do
|
5
|
+
let(:books) { open_struct_books }
|
6
|
+
let(:a_tale) { books.first }
|
7
|
+
let(:order) { MundaneSearch::Filters::Order }
|
8
|
+
it "should order by title" do
|
9
|
+
books.reverse!
|
10
|
+
filter = order.new(books, {'sort' => "title"}, {param_key: 'sort'})
|
11
|
+
|
12
|
+
filter.filtered_collection.first.must_equal(a_tale)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe MundaneSearch::Filters::Order::ActiveRecord do
|
16
|
+
let(:order) { MundaneSearch::Filters::Order::ActiveRecord }
|
17
|
+
it "should filter with 'where'" do
|
18
|
+
collection = Minitest::Mock.new
|
19
|
+
params = { 'sort' => "title" }
|
20
|
+
result = Object.new
|
21
|
+
|
22
|
+
filter = order.new(collection, params, param_key: 'sort')
|
23
|
+
collection.expect(:order, result, ["title ASC"])
|
24
|
+
filter.filtered_collection.must_equal(result)
|
25
|
+
collection.verify
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -53,6 +53,10 @@ describe MundaneSearch::Filters::Typical do
|
|
53
53
|
it "should return param value matching param_key" do
|
54
54
|
typical(param_key: "foo").match_value.must_equal "bar"
|
55
55
|
end
|
56
|
+
|
57
|
+
it "should use explicit match value when supplied" do
|
58
|
+
typical(match_value: "foo").match_value.must_equal "foo"
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
describe "#param_key_type" do
|
data/spec/minitest_helper.rb
CHANGED
@@ -70,6 +70,20 @@ def params
|
|
70
70
|
{ 'foo' => 'bar' }
|
71
71
|
end
|
72
72
|
|
73
|
+
def requirements_for_search_url_for_tests!
|
74
|
+
require 'action_dispatch/routing/polymorphic_routes'
|
75
|
+
def view_with_url_class
|
76
|
+
Class.new do
|
77
|
+
include ActionDispatch::Routing::PolymorphicRoutes
|
78
|
+
%w(generic_search_url).each do |path|
|
79
|
+
define_method path do |a=nil,b=nil|
|
80
|
+
"/#{path}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
73
87
|
def requirements_for_form_for_tests!
|
74
88
|
require_relative 'demo_data'
|
75
89
|
require 'active_support/concern'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'minitest_helper'
|
2
|
+
|
3
|
+
requirements_for_search_url_for_tests!
|
4
|
+
|
5
|
+
describe "integration search_url_for" do
|
6
|
+
let(:result_class) { Class.new(MundaneSearch::Result) }
|
7
|
+
let(:result) { result_class.new(open_struct_books, params) }
|
8
|
+
let(:result_model) { result.to_model }
|
9
|
+
let(:search_url_viewed_class) do
|
10
|
+
Class.new(view_with_url_class) do
|
11
|
+
include MundaneSearch::ViewHelpers
|
12
|
+
end
|
13
|
+
end
|
14
|
+
let(:search_url_view) { search_url_viewed_class.new }
|
15
|
+
|
16
|
+
it "should generate url" do
|
17
|
+
form = search_url_view.search_url_for(result_model) { }
|
18
|
+
form.must_match %r{\A/}
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mundane-search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -230,6 +230,7 @@ files:
|
|
230
230
|
- lib/mundane-search/filters/blank_params_are_nil.rb
|
231
231
|
- lib/mundane-search/filters/exact_match.rb
|
232
232
|
- lib/mundane-search/filters/operator.rb
|
233
|
+
- lib/mundane-search/filters/order.rb
|
233
234
|
- lib/mundane-search/filters/shortcuts.rb
|
234
235
|
- lib/mundane-search/filters/typical.rb
|
235
236
|
- lib/mundane-search/initial_stack.rb
|
@@ -257,6 +258,8 @@ files:
|
|
257
258
|
- spec/filters/exact_match_spec.rb
|
258
259
|
- spec/filters/operator_integration_spec.rb
|
259
260
|
- spec/filters/operator_spec.rb
|
261
|
+
- spec/filters/order_integration_spec.rb
|
262
|
+
- spec/filters/order_spec.rb
|
260
263
|
- spec/filters/shortcuts_integration_spec.rb
|
261
264
|
- spec/filters/shortcuts_spec.rb
|
262
265
|
- spec/filters/typical_spec.rb
|
@@ -268,6 +271,7 @@ files:
|
|
268
271
|
- spec/result_model_spec.rb
|
269
272
|
- spec/result_spec.rb
|
270
273
|
- spec/search_form_for_integration_spec.rb
|
274
|
+
- spec/search_url_for_integration_spec.rb
|
271
275
|
- spec/simple_form_integration_spec.rb
|
272
276
|
- spec/simple_search_form_for_integration_spec.rb
|
273
277
|
- spec/stack_spec.rb
|
@@ -285,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
285
289
|
version: '0'
|
286
290
|
segments:
|
287
291
|
- 0
|
288
|
-
hash: -
|
292
|
+
hash: -2671507479759182852
|
289
293
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
290
294
|
none: false
|
291
295
|
requirements:
|
@@ -294,10 +298,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
294
298
|
version: '0'
|
295
299
|
segments:
|
296
300
|
- 0
|
297
|
-
hash: -
|
301
|
+
hash: -2671507479759182852
|
298
302
|
requirements: []
|
299
303
|
rubyforge_project:
|
300
|
-
rubygems_version: 1.8.
|
304
|
+
rubygems_version: 1.8.23
|
301
305
|
signing_key:
|
302
306
|
specification_version: 3
|
303
307
|
summary: Makes everyday search easy-ish.
|
@@ -318,6 +322,8 @@ test_files:
|
|
318
322
|
- spec/filters/exact_match_spec.rb
|
319
323
|
- spec/filters/operator_integration_spec.rb
|
320
324
|
- spec/filters/operator_spec.rb
|
325
|
+
- spec/filters/order_integration_spec.rb
|
326
|
+
- spec/filters/order_spec.rb
|
321
327
|
- spec/filters/shortcuts_integration_spec.rb
|
322
328
|
- spec/filters/shortcuts_spec.rb
|
323
329
|
- spec/filters/typical_spec.rb
|
@@ -329,6 +335,7 @@ test_files:
|
|
329
335
|
- spec/result_model_spec.rb
|
330
336
|
- spec/result_spec.rb
|
331
337
|
- spec/search_form_for_integration_spec.rb
|
338
|
+
- spec/search_url_for_integration_spec.rb
|
332
339
|
- spec/simple_form_integration_spec.rb
|
333
340
|
- spec/simple_search_form_for_integration_spec.rb
|
334
341
|
- spec/stack_spec.rb
|