philter 0.7.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -1
- data/README.md +126 -26
- data/lib/array.rb +24 -33
- data/lib/base.rb +166 -102
- data/lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 752a73c7c043fd49ebb875fca66209e6865b1f17
|
4
|
+
data.tar.gz: 2c010a42446deff32ac4edc8bb2a0934333f8910
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db08c41adc22da507100dba892ed3329a0d2e6e7a352cd459408ad30cb078fafd06988d228c646a111d2cdd4e606e9e80591b8445611d53f9b1026b88b96e506
|
7
|
+
data.tar.gz: 4449e25ad6b6a348d15edb3ae3292b16bb95eef9f52749598a1cfc486f613a6186decc62a481c8bd9d28da1a55e321bad169cde3ff15bed5492844ce9334d24f
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,33 @@
|
|
1
|
-
|
1
|
+
v1.0.0 [☰](https://github.com/marcomd/Philter/compare/v0.8.0...v1.0.0) May 25th, 2016
|
2
|
+
------------------------------
|
3
|
+
* Code revolution: more simple, secure and readable
|
4
|
+
* Performance: now it use grep for simple search
|
5
|
+
* Test:
|
6
|
+
* wide coverage with 37 unit tests and 137 assertions
|
7
|
+
* updated 8 performance tests
|
8
|
+
* Functional:
|
9
|
+
* now you can pass a block to update or completely change any array's element
|
10
|
+
* you can search multiple attributes with and boolean operator. It's also possible use `or` as option
|
11
|
+
* added option `everywhere` to search an attribute also in simple value.
|
12
|
+
Examples:
|
13
|
+
```ruby
|
14
|
+
[:first, :second, {id: 1, tag: :first}, {id: 2, tag: :second}].philter tag: :first
|
15
|
+
=> [{:id=>1, :tag=>:first}]
|
16
|
+
[:first, :second, {id: 1, tag: :first}, {id: 2, tag: :second}].philter({tag: :first}, everywhere: true)
|
17
|
+
=> [:first, {:id=>1, :tag=>:first}]
|
18
|
+
```
|
19
|
+
|
20
|
+
|
21
|
+
v0.8.0 May 24th, 2016
|
22
|
+
------------------------------
|
23
|
+
* Added philter by class, example:
|
24
|
+
```ruby
|
25
|
+
[:first, 'second'].philter Symbol
|
26
|
+
=> [:first]
|
27
|
+
```
|
28
|
+
* Many internal changement
|
29
|
+
|
30
|
+
v0.7.0 [☰](https://github.com/marcomd/Philter/compare/v0.6.0...v0.7.0) May 24th, 2016
|
2
31
|
------------------------------
|
3
32
|
* Added performance tests
|
4
33
|
|
data/README.md
CHANGED
@@ -36,6 +36,10 @@ require 'philter'
|
|
36
36
|
%w[red green blue].philter %w(red blue)
|
37
37
|
=> ["red", "blue"]
|
38
38
|
|
39
|
+
# You can pass a block
|
40
|
+
[1,2,3].philter([1,2]){|e|e*2}
|
41
|
+
=> [2, 4]
|
42
|
+
|
39
43
|
# Array of hashes
|
40
44
|
[
|
41
45
|
{id: 1, name: 'Mark' },
|
@@ -72,6 +76,39 @@ require 'philter'
|
|
72
76
|
{id: 3, name: 'Bill', email: 'bill@live.com' }
|
73
77
|
].philter({email: /@gmail/}, get: :name)
|
74
78
|
=> ["Mark", "Larry"]
|
79
|
+
|
80
|
+
# Philter with more attributes
|
81
|
+
[
|
82
|
+
{id: 1, name: 'Mark', email: 'mark@gmail.com' },
|
83
|
+
{id: 2, name: 'Larry', email: 'larry@gmail.com' },
|
84
|
+
{id: 3, name: 'Bill', email: 'bill@live.com' }
|
85
|
+
].philter name: /M.+/, email: /@gmail/
|
86
|
+
=> [{:id=>1, :name=>"Mark", :email=>"mark@gmail.com"}]
|
87
|
+
|
88
|
+
# Philter with an attribute or another
|
89
|
+
[
|
90
|
+
{id: 1, name: 'Mark', email: 'mark@gmail.com' },
|
91
|
+
{id: 2, name: 'Larry', email: 'larry@gmail.com' },
|
92
|
+
{id: 3, name: 'Bill', email: 'bill@live.com' }
|
93
|
+
].philter({name: /M.+/, email: /@live/}, or: true)
|
94
|
+
=> [{:id=>1, :name=>"Mark", :email=>"mark@gmail.com"}, {:id=>3, :name=>"Bill", :email=>"bill@live.com"}]
|
95
|
+
|
96
|
+
# A bit of magic
|
97
|
+
# Select and update attributes
|
98
|
+
[
|
99
|
+
{id: 1, name: 'Mark', email: 'mark@gmail.com' },
|
100
|
+
{id: 2, name: 'Larry', email: 'larry@gmail.com' },
|
101
|
+
{id: 3, name: 'Bill', email: 'bill@live.com' }
|
102
|
+
].philter({email: /@gmail/}){|e| e[:name] << ' use gmail!'}
|
103
|
+
=> ["Mark use gmail!", "Larry use gmail!"]
|
104
|
+
|
105
|
+
# Add attributes
|
106
|
+
[
|
107
|
+
{id: 1, name: 'Mark', email: 'mark@gmail.com' },
|
108
|
+
{id: 2, name: 'Larry', email: 'larry@gmail.com' },
|
109
|
+
{id: 3, name: 'Bill', email: 'bill@live.com' }
|
110
|
+
].philter({email: /@gmail/}){|e| e[:surname] = 'unknown';e }
|
111
|
+
=> :try_yourself
|
75
112
|
```
|
76
113
|
|
77
114
|
Get the trace with the option `debug: true`
|
@@ -115,31 +152,73 @@ cities.philter id: 1
|
|
115
152
|
cities.philter code: 'PA'
|
116
153
|
=> [#<City id: 4, name: "Palermo", code: "PA", region: "Sicilia", created_at: "2016-05-10 09:08:13", updated_at: "2016-05-10 09:08:13">]
|
117
154
|
|
118
|
-
|
119
|
-
|
155
|
+
# Pass a block to select, update or change the result
|
156
|
+
cities.philter(region: /\Alomb/i){|city| "#{city.name}-#{city.code}"}
|
157
|
+
=> ["Milano-MI", "Lecco-LC", "Pavia-PV", "Piacenza-PC"]
|
158
|
+
|
120
159
|
```
|
121
160
|
|
122
161
|
## Performance
|
123
162
|
|
124
|
-
|
163
|
+
Since version `1.0.0` performance are greatly improved!
|
164
|
+
Ruby 2.2.3p173 on windows 7 with i5 3570K Ivy Bridge @4200 Mhz Ram 16Gb 10-10-10-27 2T @686Mhz
|
125
165
|
|
126
166
|
```ruby
|
127
167
|
require 'benchmark'
|
168
|
+
require 'philter'
|
128
169
|
|
129
170
|
ar_test = 100.times.map{|n| n}
|
130
171
|
Benchmark.bmbm do |x|
|
131
|
-
x.report("philter: ") {
|
132
|
-
x.report("grep: ") {
|
172
|
+
x.report("philter: ") { 10_000.times { ar_test.philter 1 } }
|
173
|
+
x.report("grep: ") { 10_000.times { ar_test.grep 1 } }
|
133
174
|
end
|
134
175
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
176
|
+
#version 1.0.0
|
177
|
+
user system total real
|
178
|
+
philter: 0.031000 0.000000 0.031000 ( 0.021759)
|
179
|
+
grep: 0.016000 0.000000 0.016000 ( 0.007115)
|
139
180
|
|
181
|
+
#version 0.7.0
|
140
182
|
user system total real
|
141
|
-
philter:
|
142
|
-
grep: 0.
|
183
|
+
philter: 9.204000 0.000000 9.204000 ( 9.254443)
|
184
|
+
grep: 0.062000 0.000000 0.062000 ( 0.054257)
|
185
|
+
```
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
range = 1..10
|
189
|
+
Benchmark.bmbm do |x|
|
190
|
+
x.report("philter: ") { 10_000.times { ar_test.philter range } }
|
191
|
+
x.report("grep: ") { 10_000.times { ar_test.grep range } }
|
192
|
+
end
|
193
|
+
|
194
|
+
#version 1.0.0
|
195
|
+
user system total real
|
196
|
+
philter: 0.015000 0.000000 0.015000 ( 0.023891)
|
197
|
+
grep: 0.000000 0.000000 0.000000 ( 0.009134)
|
198
|
+
|
199
|
+
#version 0.7.0
|
200
|
+
=> Range was not managed
|
201
|
+
user system total real
|
202
|
+
philter: 91.136000 0.000000 91.136000 ( 91.305855)
|
203
|
+
grep: 0.172000 0.000000 0.172000 ( 0.182490)
|
204
|
+
```
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
ar_search = [1,3,5,7]
|
208
|
+
Benchmark.bmbm do |x|
|
209
|
+
x.report("philter: ") { 10_000.times { ar_test.philter ar_search } }
|
210
|
+
x.report("select: ") { 10_000.times { ar_test.select{|item| ar_search.include? item } } }
|
211
|
+
end
|
212
|
+
|
213
|
+
#version 1.0.0
|
214
|
+
user system total real
|
215
|
+
philter: 0.062000 0.000000 0.062000 ( 0.052933)
|
216
|
+
select: 0.031000 0.000000 0.031000 ( 0.022178)
|
217
|
+
|
218
|
+
#version 0.7.0
|
219
|
+
user system total real
|
220
|
+
philter: 36.176000 0.000000 36.176000 ( 36.182101)
|
221
|
+
select: 0.078000 0.000000 0.078000 ( 0.073341)
|
143
222
|
```
|
144
223
|
|
145
224
|
```ruby
|
@@ -148,31 +227,33 @@ Benchmark.bmbm do |x|
|
|
148
227
|
x.report("select: ") { 1_000.times { ar_test.select {|item| item < 50} } }
|
149
228
|
end
|
150
229
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
230
|
+
#version 1.0.0
|
231
|
+
user system total real
|
232
|
+
philter: 2.855000 0.000000 2.855000 ( 2.851040)
|
233
|
+
select: 0.015000 0.000000 0.015000 ( 0.004312)
|
155
234
|
|
235
|
+
#version 0.7.0
|
156
236
|
user system total real
|
157
237
|
philter: 3.744000 0.000000 3.744000 ( 3.746851)
|
158
238
|
select: 0.016000 0.000000 0.016000 ( 0.004338)
|
159
239
|
```
|
160
240
|
|
161
241
|
```ruby
|
162
|
-
ar_test = [ {id: 1, name: 'Mark',
|
163
|
-
{id: 2, name: 'Bill', email: 'bill@live.com'},
|
164
|
-
{id: 3, name: 'Larry', email: 'larry@gmail.com'}]
|
242
|
+
ar_test = [ {id: 1, name: 'Mark', email: 'mark@gmail.com' },
|
243
|
+
{id: 2, name: 'Bill', email: 'bill@live.com' },
|
244
|
+
{id: 3, name: 'Larry', email: 'larry@gmail.com' }]
|
165
245
|
regexp = /\A.+gmail/
|
166
246
|
Benchmark.bmbm do |x|
|
167
247
|
x.report("philter: ") { 10_000.times { ar_test.philter email: regexp } }
|
168
248
|
x.report("select: ") { 10_000.times { ar_test.select {|item| item[:email] =~ regexp} } }
|
169
249
|
end
|
170
250
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
251
|
+
#version 1.0.0
|
252
|
+
user system total real
|
253
|
+
philter: 0.218000 0.000000 0.218000 ( 0.221822)
|
254
|
+
select: 0.000000 0.000000 0.000000 ( 0.003418)
|
175
255
|
|
256
|
+
#version 0.7.0
|
176
257
|
user system total real
|
177
258
|
philter: 0.468000 0.000000 0.468000 ( 0.473782)
|
178
259
|
select: 0.000000 0.000000 0.000000 ( 0.003429)
|
@@ -186,12 +267,14 @@ Ruby `1.9+`
|
|
186
267
|
|
187
268
|
gem install philter
|
188
269
|
|
189
|
-
To use it in a
|
270
|
+
To use it in a bundle, add to gem file `gem 'philter'` and run `bundle install`
|
190
271
|
|
191
272
|
## To Do
|
192
273
|
|
193
|
-
|
194
|
-
|
274
|
+
- [x] Add boolean operator to chain of conditions `v1.0.0`
|
275
|
+
- [x] Improve performance keeping the operations's trace `v1.0.0`
|
276
|
+
- [x] Add block `v1.0.0`
|
277
|
+
- [ ] Increase performance further
|
195
278
|
|
196
279
|
## Contributing
|
197
280
|
|
@@ -203,6 +286,8 @@ To use it in a rails project, add to gem file `gem 'philter'` and run `bundle in
|
|
203
286
|
|
204
287
|
## Testing
|
205
288
|
|
289
|
+
Wide coverage with `37 unit tests` and `137 assertions`
|
290
|
+
|
206
291
|
To test locally install the development requirements
|
207
292
|
|
208
293
|
bundle install
|
@@ -215,7 +300,22 @@ Performance tests are calibrated to not exceed 1.2 seconds on my pc with a toler
|
|
215
300
|
|
216
301
|
bundle exec ruby test\performance_test.rb
|
217
302
|
|
218
|
-
|
303
|
+
```
|
304
|
+
Loaded suite test/performance_test
|
305
|
+
Started
|
306
|
+
........
|
307
|
+
|
308
|
+
Finished in 8.505 seconds.
|
309
|
+
--------------------------------------------------------------------------------
|
310
|
+
|
311
|
+
8 tests, 8 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
|
312
|
+
100% passed
|
313
|
+
--------------------------------------------------------------------------------
|
314
|
+
|
315
|
+
0.94 tests/s, 0.94 assertions/s
|
316
|
+
```
|
317
|
+
|
318
|
+
If you have a very slow pc it could not pass. In this case you can pass a higher tolerance value as argument, for example 3 seconds:
|
219
319
|
|
220
320
|
bundle exec ruby test\performance_test.rb 3.0
|
221
321
|
|
data/lib/array.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Array
|
2
2
|
include Philter::Base
|
3
|
-
def philter search=nil, options={}
|
3
|
+
def philter search=nil, options={}, &block
|
4
4
|
options = {
|
5
5
|
get: nil,
|
6
6
|
debug: false
|
@@ -9,41 +9,32 @@ class Array
|
|
9
9
|
puts philter_help if options[:debug]
|
10
10
|
raise "Specify search parameter!"
|
11
11
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
|
13
|
+
apply_block = true
|
14
|
+
results =
|
15
|
+
case search.class.name
|
16
|
+
when "Hash"
|
17
|
+
print " h. " if options[:debug]
|
18
|
+
phil_search_by_attributes search, options
|
19
|
+
when "String"
|
20
|
+
print " s. " if options[:debug]
|
21
|
+
operator = phil_get_operator search
|
22
|
+
operator ? phil_search_with_operator(search, operator: operator) : self.grep(search)
|
23
|
+
when "Array"
|
24
|
+
print " a. " if options[:debug]
|
25
|
+
phil_search_by_array search, options
|
24
26
|
else
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
print " c. " if options[:debug]
|
29
|
-
selected = phil_evaluate item, nil, search, :simple, options.merge(operator: '==')
|
30
|
-
puts " #{'=> X' if selected}" if options[:debug]
|
31
|
-
end
|
32
|
-
if selected
|
33
|
-
results <<
|
34
|
-
if options[:get]
|
35
|
-
if item.respond_to? options[:get]
|
36
|
-
item.send options[:get]
|
37
|
-
elsif item.respond_to? '[]'
|
38
|
-
item[options[:get]]
|
39
|
-
end
|
40
|
-
else
|
41
|
-
item
|
42
|
-
end
|
43
|
-
end
|
27
|
+
puts " g. #{search}" if options[:debug]
|
28
|
+
apply_block = false
|
29
|
+
self.grep(search, &block)
|
44
30
|
end
|
31
|
+
|
45
32
|
puts "------------------" if options[:debug]
|
46
33
|
puts " #{results ? results.size : 'No'} item#{results && results.size == 1 ? '' : 's'} found" if options[:debug]
|
47
|
-
|
34
|
+
if block_given? && apply_block
|
35
|
+
results.map{|item| block.call(item)}
|
36
|
+
else
|
37
|
+
results
|
38
|
+
end
|
48
39
|
end
|
49
40
|
end
|
data/lib/base.rb
CHANGED
@@ -1,127 +1,191 @@
|
|
1
1
|
module Philter
|
2
2
|
module Base
|
3
3
|
private
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
People.philter name: 'Mario'
|
15
|
-
People.philter email: /\A.+@gmail/
|
16
|
-
Use option get: to select an attribute
|
17
|
-
People.philter {id: 1}, get: :surname
|
18
|
-
Use option debug: to watch the selection
|
19
|
-
Articles.philter {id: 1}, debug: true
|
20
|
-
*************************************************************************
|
21
|
-
HELP
|
4
|
+
|
5
|
+
def phil_search_with_operator search, options={}
|
6
|
+
results = []
|
7
|
+
self.each do |item|
|
8
|
+
puts "item #{item.class.name} #{item}" if options[:debug]
|
9
|
+
selected = phil_evaluate item, search, options
|
10
|
+
puts " #{'=> X' if selected}" if options[:debug]
|
11
|
+
results << item if selected
|
12
|
+
end
|
13
|
+
results
|
22
14
|
end
|
23
15
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
16
|
+
def phil_search_by_array search, options={}
|
17
|
+
puts "search #{search} (#{search.class.name}) " if options[:debug]
|
18
|
+
search_same_class = false
|
19
|
+
search.inject{|prev, cur| search_same_class=prev.class == cur.class; cur }
|
20
|
+
if search_same_class
|
21
|
+
self.select do |item|
|
22
|
+
if search.first.class.name == 'Class'
|
23
|
+
search.include? item.class
|
24
|
+
else
|
25
|
+
search.include? item
|
26
|
+
end
|
27
|
+
end
|
29
28
|
else
|
30
|
-
|
29
|
+
# Check every search item
|
30
|
+
search.each do |search_value|
|
31
|
+
self.select do |item|
|
32
|
+
if search_value.class.name == 'Class'
|
33
|
+
search_value == item.class
|
34
|
+
else
|
35
|
+
search_value == item
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
42
|
+
def phil_search_by_attributes search, options={}
|
43
|
+
results = []
|
44
|
+
self.each do |item|
|
45
|
+
selected = nil
|
46
|
+
# Evaluate each array's item
|
47
|
+
puts "item #{item} (#{item.class.name}) " if options[:debug]
|
48
|
+
case item.class.name
|
49
|
+
when "Array"
|
50
|
+
print " a. discarded" if options[:debug]
|
51
|
+
when "Hash"
|
52
|
+
print " h. " if options[:debug]
|
53
|
+
selected = phil_apply_attributes item, search, options
|
54
|
+
when phil_base_objects
|
55
|
+
print " b. discarded" if options[:debug]
|
56
|
+
else
|
57
|
+
print " o. " if options[:debug]
|
58
|
+
selected = phil_apply_attributes item, search, options
|
59
|
+
end
|
60
|
+
# puts " #{'=> X' if selected}" if options[:debug]
|
61
|
+
if selected
|
62
|
+
results <<
|
63
|
+
if options[:get]
|
64
|
+
if item.respond_to? options[:get]
|
65
|
+
item.send options[:get]
|
66
|
+
elsif item.respond_to? '[]'
|
67
|
+
item[options[:get]]
|
68
|
+
end
|
69
|
+
else
|
70
|
+
item
|
71
|
+
end
|
72
|
+
end
|
58
73
|
end
|
74
|
+
results
|
59
75
|
end
|
60
76
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
search.each do |value|
|
77
|
+
def phil_apply_attributes item, search, options={}
|
78
|
+
selected_or, selected_and = nil, true
|
79
|
+
search.each do |key, search_value|
|
65
80
|
# Every item must match with search options to be selected
|
66
|
-
puts "
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
selected = phil_evaluate item, nil, value, :simple, options.merge(operator: '==')
|
85
|
-
puts " #{'=> X' if selected}" if options[:debug]
|
81
|
+
puts " search: #{key}: #{search_value} (#{search_value.class.name})" if options[:debug]
|
82
|
+
case search_value.class.name
|
83
|
+
when 'Regexp'
|
84
|
+
# search: {email: /@gmail/}
|
85
|
+
print " .1 " if options[:debug]
|
86
|
+
selected = phil_evaluate item_value(item, key, options), search_value, options.merge(operator: '=~')
|
87
|
+
when 'Class'
|
88
|
+
# search: {code: String} or {code: Fixnum}
|
89
|
+
print " .2 item.class == value | #{item.class} == #{search_value}" if options[:debug]
|
90
|
+
selected = item_value(item, key, options).class == search_value
|
91
|
+
when 'Array'
|
92
|
+
# search: {id: [1,2]}
|
93
|
+
print " .3 " if options[:debug]
|
94
|
+
selected = search_value.include? item_value(item, key, options)
|
95
|
+
else
|
96
|
+
# search: {id: 2} or {id: '<3'} or any other operator
|
97
|
+
print " .4 " if options[:debug]
|
98
|
+
selected = phil_evaluate item_value(item, key, options), search_value, options.merge(operator: '==')
|
86
99
|
end
|
100
|
+
puts " #{'=> x' if selected}" if options[:debug]
|
87
101
|
selected_or = true if !selected_or && selected
|
88
102
|
selected_and = selected if selected_and
|
89
103
|
end
|
90
|
-
|
104
|
+
|
105
|
+
if options[:or]
|
106
|
+
puts " #{'=> X (Or)' if selected_or}" if options[:debug]
|
107
|
+
selected_or
|
108
|
+
else
|
109
|
+
puts " #{'=> X (And)' if selected_and}" if options[:debug]
|
110
|
+
selected_and
|
111
|
+
end
|
91
112
|
end
|
92
113
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
print " 1.y label: #{label.class.name}" if options[:debug]
|
108
|
-
if value.is_a?(Regexp)
|
109
|
-
# search: {email: /@gmail/}
|
110
|
-
print " .1 " if options[:debug]
|
111
|
-
selected = phil_evaluate item, label, value, :hash, options.merge(operator: '=~')
|
112
|
-
elsif item.is_a?(Hash) && !label.is_a?(Fixnum)
|
113
|
-
# search: {id: 1} or {'name' => 'Mark'}
|
114
|
-
# search: {id: '<3'} or any other operator
|
115
|
-
print " .2 " if options[:debug]
|
116
|
-
selected = phil_evaluate item, label, value, :hash, options.merge(operator: '==')
|
114
|
+
def item_value item, label, options={}
|
115
|
+
case item.class.name
|
116
|
+
when "Hash" then
|
117
|
+
print " v1 item[#{label}] " if options[:debug]
|
118
|
+
item[label]
|
119
|
+
when "Fixnum", "Float", "Bignum", "Symbol", "String"
|
120
|
+
print " v2 #{item.class.name} " if options[:debug]
|
121
|
+
if options[:everywhere]
|
122
|
+
print "#{item} " if options[:debug]
|
123
|
+
item
|
124
|
+
else
|
125
|
+
print "- " if options[:debug]
|
126
|
+
nil
|
127
|
+
end
|
117
128
|
else
|
118
|
-
print "
|
119
|
-
|
129
|
+
print " v3 item.#{label} " if options[:debug]
|
130
|
+
item.send(label) if item.respond_to? label
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def phil_evaluate item, value, options={}
|
135
|
+
options = {
|
136
|
+
operator: '==',
|
137
|
+
debug: false
|
138
|
+
}.merge(options)
|
139
|
+
operator = phil_get_operator value
|
140
|
+
value = operator ? value.gsub(operator,'').to_i : value
|
141
|
+
operator ||= options[:operator]
|
142
|
+
print " item #{operator} value" if options[:debug]
|
143
|
+
print " | #{item} #{operator} #{value}" if options[:debug]
|
144
|
+
case operator
|
145
|
+
when '=~' then item.to_s =~ value
|
146
|
+
when '==' then item == value
|
147
|
+
when '===' then item === value
|
148
|
+
when '>' then item > value
|
149
|
+
when '<' then item < value
|
150
|
+
when '>=' then item >= value
|
151
|
+
when '<=' then item <= value
|
152
|
+
when '!=' then item != value
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def phil_get_operator exp
|
157
|
+
return unless exp.is_a? String
|
158
|
+
regexp = "(?:<=?|>=?|!=|==|===|=~)"
|
159
|
+
if exp =~ /#{regexp}/
|
160
|
+
exp.match(/#{regexp}/).to_s
|
120
161
|
else
|
121
|
-
|
162
|
+
nil
|
122
163
|
end
|
123
|
-
puts " #{'=> X' if selected}" if options[:debug]
|
124
|
-
selected
|
125
164
|
end
|
165
|
+
|
166
|
+
def phil_base_objects
|
167
|
+
return "Fixnum", "Float", "Bignum", "Symbol", "String"
|
168
|
+
end
|
169
|
+
|
170
|
+
def philter_help
|
171
|
+
<<-HELP.gsub(/^ /, '')
|
172
|
+
*************************************************************************
|
173
|
+
Philter version #{Philter.version}
|
174
|
+
[].philter 'search', {options}
|
175
|
+
Examples:
|
176
|
+
[1,2,3].philter 1 => [1]
|
177
|
+
[1,2,3].philter [2,3] => [2, 3]
|
178
|
+
[{id: 1, name: 'Mark'},{id: 2, name: 'Bill'}].philter id: 1
|
179
|
+
Articles.philter id: 1
|
180
|
+
People.philter name: 'Mario'
|
181
|
+
People.philter email: /\A.+@gmail/
|
182
|
+
Use option get: to select an attribute
|
183
|
+
People.philter {id: 1}, get: :surname
|
184
|
+
Use option debug: to watch the selection
|
185
|
+
Articles.philter {id: 1}, debug: true
|
186
|
+
*************************************************************************
|
187
|
+
HELP
|
188
|
+
end
|
189
|
+
|
126
190
|
end
|
127
191
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: philter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marco Mastrodonato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-unit
|