philter 0.7.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|