filter_me 0.1.0 → 0.1.1
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/README.md +66 -4
- data/filter_me.gemspec +0 -1
- data/lib/filter_me/filter/arel_field_filter.rb +1 -1
- data/lib/filter_me/filter/dsl.rb +2 -4
- data/lib/filter_me/version.rb +1 -1
- data/spec/acceptance/filters/users_filter_spec.rb +16 -0
- data/spec/internal/app/filters/companies_filter.rb +5 -0
- data/spec/internal/app/filters/jobs_filter.rb +5 -0
- data/spec/internal/app/filters/users_filter.rb +1 -0
- data/spec/internal/app/models/company.rb +4 -0
- data/spec/internal/app/models/job.rb +3 -0
- data/spec/internal/app/models/user.rb +2 -0
- data/spec/internal/db/fixtures/jobs.rb +6 -0
- data/spec/internal/db/fixtures/users.rb +10 -2
- data/spec/internal/db/schema.rb +12 -0
- data/spec/unit/arel_field_filter_spec.rb +21 -4
- data/spec/unit/filter_arel_dsl_spec.rb +9 -11
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d20eaf1933fba4c0a52e4c6b04ab9e9bce510c2
|
4
|
+
data.tar.gz: eafa06100f1fd7cf77332a340f1213f7e344beae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5356b764fbe3b6a961fc1dae9a8e7b6a08dce53c4871772a13119fb0623e676acd4fa1074d7b308270d215e6dce9700cbb76ac6590c929643e8770a5891bf86
|
7
|
+
data.tar.gz: b07bbc44c7a7bd6bcec60cbfa453615e28eba848e8c30cc5d2069ac0edfb98f516ef80d26302bf0db7aa39f6188d34f062d7e6b7b87b43a49abb3b1f62e26f4f
|
data/README.md
CHANGED
@@ -1,11 +1,73 @@
|
|
1
|
-
|
2
|
-
filter_me
|
1
|
+
FilterMe
|
3
2
|
=========
|
4
3
|
|
5
|
-
|
4
|
+
[](https://travis-ci.org/Samsinite/filter_me) [](https://codeclimate.com/github/Samsinite/filter_me) [](http://badge.fury.io/rb/filter_me)
|
6
5
|
|
7
|
-
###
|
6
|
+
### A Rails/ActiveRecord filtering gem
|
8
7
|
|
8
|
+
FilterMe provids helpers and classes that provides filtering using Ruby classes and object oriented development
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
``` ruby
|
12
|
+
gem "filter_me", "0.1.0"
|
13
|
+
```
|
14
|
+
|
15
|
+
## Filter:
|
16
|
+
\* Highly subject to change as the API moves closer to 1.0
|
17
|
+
``` ruby
|
18
|
+
class AccountsFilter < FilterMe::ActiveRecordFilter
|
19
|
+
model Account
|
20
|
+
|
21
|
+
field :type, [:matches, :eq, :not_eq] # Uses arel, so any Arel::Predications method should work
|
22
|
+
field :cost, [:lt, :gt, :lteq, :gteq, :eq] # Uses arel, so any Arel::Predications method should work
|
23
|
+
end
|
24
|
+
|
25
|
+
class AccountsController < ApplicationController
|
26
|
+
include FilterMe
|
27
|
+
|
28
|
+
def index
|
29
|
+
@accounts = filter_me(Account.all)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Given a controller that recieves params like the following:
|
35
|
+
``` ruby
|
36
|
+
params # => {filters: {type: {eq: "admin"} } }
|
37
|
+
```
|
38
|
+
|
39
|
+
The following SQL would be performed (Using ActiveRecord):
|
40
|
+
``` SQL
|
41
|
+
SELECT "accounts".* FROM "accounts" WHERE ("accounts"."type" = "admin")
|
42
|
+
```
|
43
|
+
|
44
|
+
## Nested Filtering:
|
45
|
+
``` ruby
|
46
|
+
class UsersFilter < FilterMe::ActiveRecordFilter
|
47
|
+
model User
|
48
|
+
|
49
|
+
association :account, :filter_class => AccountsFilter
|
50
|
+
field :username, [:matches, :eq, :not_eq] # Uses arel, so any Arel::Predications method should work
|
51
|
+
end
|
52
|
+
|
53
|
+
class UsersController < ApplicationController
|
54
|
+
include FilterMe
|
55
|
+
|
56
|
+
def index
|
57
|
+
@users = filter_me(User.all)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
With the following params:
|
63
|
+
``` ruby
|
64
|
+
params # => {:filters => {:email => {:matches => "%test.com"}, :account => {:cost => {:lt => 100000} } } }
|
65
|
+
```
|
66
|
+
Performs:
|
67
|
+
``` SQL
|
68
|
+
SELECT "users".* FROM "users" INNER JOIN "accounts" ON "accounts"."user_id" = "users"."id"
|
69
|
+
WHERE ("users"."email" LIKE '%test.com') AND ("accounts"."cost" < 100000)
|
70
|
+
```
|
9
71
|
|
10
72
|
## License
|
11
73
|
Copyright (c) 2014, Filter Me is developed and maintained by Sam Clopton, and is released under the open MIT Licence.
|
data/filter_me.gemspec
CHANGED
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_runtime_dependency 'activerecord', '>= 3.2.0'
|
22
22
|
s.add_runtime_dependency 'activesupport', '>= 3.2.0'
|
23
|
-
#s.add_runtime_dependency 'activemodel', '>= 3.2.0'
|
24
23
|
s.add_development_dependency 'combustion', '~> 0.5.1'
|
25
24
|
s.add_development_dependency 'rspec-rails', '~> 2.13'
|
26
25
|
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
data/lib/filter_me/filter/dsl.rb
CHANGED
@@ -51,14 +51,12 @@ module FilterMe
|
|
51
51
|
private
|
52
52
|
|
53
53
|
def filter(name, klass, configuration, association = nil)
|
54
|
-
this = self
|
55
54
|
filter_class.send(:define_method, name) do |relation, filters|
|
56
55
|
filter = klass.new(filters, configuration)
|
57
56
|
if association
|
58
|
-
relation
|
59
|
-
filter.filter(relation)
|
57
|
+
relation.joins(name.to_sym).merge(filter.filter(relation))
|
60
58
|
else
|
61
|
-
relation.
|
59
|
+
relation.merge(filter.filter(relation))
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
data/lib/filter_me/version.rb
CHANGED
@@ -48,4 +48,20 @@ describe UsersFilter do
|
|
48
48
|
expect(user.account.cost).to be < 100000
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
it "can do a deeply nested filter" do
|
53
|
+
mock_controller.params = {:filters => {
|
54
|
+
:businesses => {
|
55
|
+
:jobs => {:name => {:matches => "find%"}}
|
56
|
+
}
|
57
|
+
}}
|
58
|
+
|
59
|
+
mock_controller.index.each do |user|
|
60
|
+
user.businesses.each do |business|
|
61
|
+
business.jobs.each do |job|
|
62
|
+
expect(job.name).to start_with "find"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
51
67
|
end
|
@@ -8,19 +8,27 @@ module Fixtures
|
|
8
8
|
user.create_account!(:cost => 100000)
|
9
9
|
end
|
10
10
|
|
11
|
-
User.create! do |user|
|
11
|
+
user = User.create! do |user|
|
12
12
|
user.username = "test2"
|
13
13
|
user.email = "test2@test.com"
|
14
14
|
|
15
15
|
user.create_account!(:cost => 50000)
|
16
16
|
end
|
17
|
+
business = user.businesses.create! do |business|
|
18
|
+
business.name = "Test"
|
19
|
+
end
|
20
|
+
business.jobs.create!(:name => "find_me")
|
17
21
|
|
18
|
-
User.create! do |user|
|
22
|
+
user = User.create! do |user|
|
19
23
|
user.username = "test3"
|
20
24
|
user.email = "test3@spaz.com"
|
21
25
|
|
22
26
|
user.create_account!(:cost => 10000)
|
23
27
|
end
|
28
|
+
business = user.businesses.create! do |business|
|
29
|
+
business.name = "Test2"
|
30
|
+
end
|
31
|
+
business.jobs.create!(:name => "dont_find_me")
|
24
32
|
end
|
25
33
|
end
|
26
34
|
end
|
data/spec/internal/db/schema.rb
CHANGED
@@ -10,4 +10,16 @@ ActiveRecord::Schema.define do
|
|
10
10
|
t.integer :cost
|
11
11
|
t.timestamps
|
12
12
|
end
|
13
|
+
|
14
|
+
create_table :companies, :force => true do |t|
|
15
|
+
t.integer :owner_id
|
16
|
+
t.string :name
|
17
|
+
t.timestamps
|
18
|
+
end
|
19
|
+
|
20
|
+
create_table :jobs, :force => true do |t|
|
21
|
+
t.integer :company_id
|
22
|
+
t.string :name
|
23
|
+
t.timestamps
|
24
|
+
end
|
13
25
|
end
|
@@ -70,7 +70,12 @@ describe FilterMe::Filter::ArelFieldFilter do
|
|
70
70
|
relation_mock = double("relation")
|
71
71
|
|
72
72
|
arel_filter = arel_table[field].lt(10)
|
73
|
-
|
73
|
+
|
74
|
+
expect(model_class).to receive(:where) do |arel_combine_filter|
|
75
|
+
expect(arel_combine_filter).to eq(arel_filter)
|
76
|
+
end
|
77
|
+
|
78
|
+
field_filter.filter(relation_mock)
|
74
79
|
end
|
75
80
|
|
76
81
|
it "builds the correct arel filter with one filter type of two filter values" do
|
@@ -78,7 +83,11 @@ describe FilterMe::Filter::ArelFieldFilter do
|
|
78
83
|
relation_mock = double("relation")
|
79
84
|
|
80
85
|
arel_filter = arel_table[field].matches("%hey%").and(arel_table[field].matches("%hi%"))
|
81
|
-
expect(
|
86
|
+
expect(model_class).to receive(:where) do |arel_combine_filter|
|
87
|
+
expect(arel_combine_filter).to eq(arel_filter)
|
88
|
+
end
|
89
|
+
|
90
|
+
field_filter.filter(relation_mock)
|
82
91
|
end
|
83
92
|
|
84
93
|
it "builds the correct arel filter with two filter types of one filter value each" do
|
@@ -86,7 +95,11 @@ describe FilterMe::Filter::ArelFieldFilter do
|
|
86
95
|
relation_mock = double("relation")
|
87
96
|
|
88
97
|
arel_filter = arel_table[field].lt(10).and(arel_table[field].gt(1))
|
89
|
-
expect(
|
98
|
+
expect(model_class).to receive(:where) do |arel_combine_filter|
|
99
|
+
expect(arel_combine_filter).to eq(arel_filter)
|
100
|
+
end
|
101
|
+
|
102
|
+
field_filter.filter(relation_mock)
|
90
103
|
end
|
91
104
|
|
92
105
|
it "builds the correct arel filter with two filter types of two filter value each" do
|
@@ -97,7 +110,11 @@ describe FilterMe::Filter::ArelFieldFilter do
|
|
97
110
|
.and(arel_table[field].lt("z")
|
98
111
|
.and(arel_table[field].matches("%hey%")
|
99
112
|
.and(arel_table[field].matches("%hi%"))))
|
100
|
-
expect(
|
113
|
+
expect(model_class).to receive(:where) do |arel_combine_filter|
|
114
|
+
expect(arel_combine_filter).to eq(arel_filter)
|
115
|
+
end
|
116
|
+
|
117
|
+
field_filter.filter(relation_mock)
|
101
118
|
end
|
102
119
|
end
|
103
120
|
end
|
@@ -18,7 +18,7 @@ describe FilterMe::Filter::ArelDSL do
|
|
18
18
|
it "initializes a ArelFieldFilter instance with the values to filter and the filter field configuration" do
|
19
19
|
filters = [:test1, :test2]
|
20
20
|
relation_mock = double("relation")
|
21
|
-
|
21
|
+
allow(relation_mock).to receive(:merge)
|
22
22
|
|
23
23
|
model_mock = double("model")
|
24
24
|
|
@@ -26,8 +26,8 @@ describe FilterMe::Filter::ArelDSL do
|
|
26
26
|
obj.whitelisted_filters == self.whitelisted_filters
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
allow(
|
29
|
+
field_filter_instance_mock = double("field filter instance")
|
30
|
+
allow(field_filter_instance_mock).to receive(:filter)
|
31
31
|
|
32
32
|
field_filter_class = double("field filter class")
|
33
33
|
allow(field_filter_class).to receive(:new) do |filters, configuration|
|
@@ -38,7 +38,7 @@ describe FilterMe::Filter::ArelDSL do
|
|
38
38
|
:model_class => model_mock
|
39
39
|
})
|
40
40
|
|
41
|
-
|
41
|
+
field_filter_instance_mock
|
42
42
|
end
|
43
43
|
|
44
44
|
stub_const("FilterMe::Filter::ArelFieldFilter", field_filter_class)
|
@@ -59,12 +59,12 @@ describe FilterMe::Filter::ArelDSL do
|
|
59
59
|
|
60
60
|
it "calls filter on the initialized ArelFieldFilter instance with the relation" do
|
61
61
|
relation_mock = double("relation")
|
62
|
-
|
62
|
+
allow(relation_mock).to receive(:merge)
|
63
63
|
|
64
64
|
model_mock = double("model")
|
65
65
|
|
66
66
|
field_filter_instance = double("field filter instance")
|
67
|
-
expect(field_filter_instance).to receive(:filter)
|
67
|
+
expect(field_filter_instance).to receive(:filter).once
|
68
68
|
|
69
69
|
field_filter_class = double("field filter class")
|
70
70
|
allow(field_filter_class).to receive(:new) { |filters, configuration| field_filter_instance }
|
@@ -83,7 +83,7 @@ describe FilterMe::Filter::ArelDSL do
|
|
83
83
|
|
84
84
|
filter_instance = filter_class.new
|
85
85
|
|
86
|
-
|
86
|
+
filter_instance.test(relation_mock, [:test1, :test2])
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -107,7 +107,7 @@ describe FilterMe::Filter::ArelDSL do
|
|
107
107
|
filters = [:test1, :test2]
|
108
108
|
relation_mock = double("relation")
|
109
109
|
allow(relation_mock).to receive(:joins) { relation_mock }
|
110
|
-
allow(relation_mock).to receive(:
|
110
|
+
allow(relation_mock).to receive(:merge)
|
111
111
|
|
112
112
|
model = double("model")
|
113
113
|
allow(model).to receive(:name) { "Model" }
|
@@ -116,8 +116,6 @@ describe FilterMe::Filter::ArelDSL do
|
|
116
116
|
allow(mock_association_filter).to receive(:filter) { relation_mock }
|
117
117
|
|
118
118
|
mock_association_filter_class = double("assocation filter class")
|
119
|
-
mock_association_filter_class.stub(:new).and_return(mock_association_filter)
|
120
|
-
|
121
119
|
expect(mock_association_filter_class).to receive(:new) do |filters, configuration|
|
122
120
|
expect(filters).to eq(filters)
|
123
121
|
expect(configuration).to eq({})
|
@@ -149,7 +147,7 @@ describe FilterMe::Filter::ArelDSL do
|
|
149
147
|
filters = [:test1, :test2]
|
150
148
|
relation_mock = double("relation")
|
151
149
|
allow(relation_mock).to receive(:joins) { relation_mock }
|
152
|
-
allow(relation_mock).to receive(:
|
150
|
+
allow(relation_mock).to receive(:merge)
|
153
151
|
|
154
152
|
model = double("model")
|
155
153
|
allow(model).to receive(:name) { "Model" }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filter_me
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Clopton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -106,11 +106,16 @@ files:
|
|
106
106
|
- spec/acceptance/filters/accounts_filter_spec.rb
|
107
107
|
- spec/acceptance/filters/users_filter_spec.rb
|
108
108
|
- spec/internal/app/filters/accounts_filter.rb
|
109
|
+
- spec/internal/app/filters/companies_filter.rb
|
110
|
+
- spec/internal/app/filters/jobs_filter.rb
|
109
111
|
- spec/internal/app/filters/users_filter.rb
|
110
112
|
- spec/internal/app/models/account.rb
|
113
|
+
- spec/internal/app/models/company.rb
|
114
|
+
- spec/internal/app/models/job.rb
|
111
115
|
- spec/internal/app/models/user.rb
|
112
116
|
- spec/internal/config/database.yml
|
113
117
|
- spec/internal/db/fixtures/accounts.rb
|
118
|
+
- spec/internal/db/fixtures/jobs.rb
|
114
119
|
- spec/internal/db/fixtures/users.rb
|
115
120
|
- spec/internal/db/schema.rb
|
116
121
|
- spec/internal/log/.gitignore
|