filter_me 0.1.0 → 0.1.1

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: 48be03e95db1c79700cb86c0e4d7d5fc3bb0105f
4
- data.tar.gz: 1dadc42cd98cf3c249139deff59d5bb381e02f93
3
+ metadata.gz: 1d20eaf1933fba4c0a52e4c6b04ab9e9bce510c2
4
+ data.tar.gz: eafa06100f1fd7cf77332a340f1213f7e344beae
5
5
  SHA512:
6
- metadata.gz: 0176700ff8445af02e848c65c8ad4e9018bce1c863ad8dab7932d349c1a5574a67c68190a0e21f28eacf320d82ef6b27c2d7a3e6414ebe7d4c656600b153d764
7
- data.tar.gz: ef3971291473338f4d2728d9fa99d11e12be7f78b3bc962da835567b2f64bea9ea6e728ba404aa3027dd10458395d18d2fefd3c72a48165fe17414f5d7089d15
6
+ metadata.gz: a5356b764fbe3b6a961fc1dae9a8e7b6a08dce53c4871772a13119fb0623e676acd4fa1074d7b308270d215e6dce9700cbb76ac6590c929643e8770a5891bf86
7
+ data.tar.gz: b07bbc44c7a7bd6bcec60cbfa453615e28eba848e8c30cc5d2069ac0edfb98f516ef80d26302bf0db7aa39f6188d34f062d7e6b7b87b43a49abb3b1f62e26f4f
data/README.md CHANGED
@@ -1,11 +1,73 @@
1
- [![Code Climate](https://codeclimate.com/github/Samsinite/filter_me.png)](https://codeclimate.com/github/Samsinite/filter_me)
2
- filter_me
1
+ FilterMe
3
2
  =========
4
3
 
5
- A Rails/ActiveRecord filtering gem
4
+ [![Build Status](https://travis-ci.org/Samsinite/filter_me.png?branch=master)](https://travis-ci.org/Samsinite/filter_me) [![Code Climate](https://codeclimate.com/github/Samsinite/filter_me.png)](https://codeclimate.com/github/Samsinite/filter_me) [![Gem Version](https://badge.fury.io/rb/filter_me.png)](http://badge.fury.io/rb/filter_me)
6
5
 
7
- ### Coming Soon to a application near you!
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'
@@ -13,7 +13,7 @@ module FilterMe
13
13
  end
14
14
 
15
15
  def filter(relation)
16
- arel_filters.inject { |arel_relation, filter| filter.and(arel_relation) }
16
+ model_class.where(arel_filters.inject { |arel_relation, filter| filter.and(arel_relation) })
17
17
  end
18
18
 
19
19
  private
@@ -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 = relation.joins(name.to_sym)
59
- filter.filter(relation)
57
+ relation.joins(name.to_sym).merge(filter.filter(relation))
60
58
  else
61
- relation.where(filter.filter(relation))
59
+ relation.merge(filter.filter(relation))
62
60
  end
63
61
  end
64
62
  end
@@ -1,3 +1,3 @@
1
1
  module FilterMe
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -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
@@ -0,0 +1,5 @@
1
+ class CompaniesFilter < FilterMe::ActiveRecordFilter
2
+ model Company
3
+
4
+ association :jobs, :filter_class => JobsFilter
5
+ end
@@ -0,0 +1,5 @@
1
+ class JobsFilter < FilterMe::ActiveRecordFilter
2
+ model Job
3
+
4
+ field :name, [:matches]
5
+ end
@@ -2,6 +2,7 @@ class UsersFilter < FilterMe::ActiveRecordFilter
2
2
  model User
3
3
 
4
4
  association :account, :filter_class => AccountsFilter
5
+ association :businesses, :filter_class => CompaniesFilter
5
6
  field :email, :all
6
7
  field :username, :matches
7
8
  end
@@ -0,0 +1,4 @@
1
+ class Company < ActiveRecord::Base
2
+ belongs_to :owner, :class_name => User
3
+ has_many :jobs, :inverse_of => :company
4
+ end
@@ -0,0 +1,3 @@
1
+ class Job < ActiveRecord::Base
2
+ belongs_to :company, :inverse_of => :jobs
3
+ end
@@ -1,3 +1,5 @@
1
1
  class User < ActiveRecord::Base
2
2
  has_one :account
3
+ has_many :businesses, :class_name => Company, :foreign_key => :owner_id, :inverse_of => :owner
4
+ has_many :jobs, :through => :businesses
3
5
  end
@@ -0,0 +1,6 @@
1
+ module Fixtures
2
+ module Accounts
3
+ def load_jobs
4
+ end
5
+ end
6
+ 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
@@ -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
- expect(field_filter.filter(relation_mock)).to eq(arel_filter)
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(field_filter.filter(relation_mock)).to eq(arel_filter)
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(field_filter.filter(relation_mock)).to eq(arel_filter)
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(field_filter.filter(relation_mock)).to eq(arel_filter)
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
- expect(relation_mock).to receive(:where) { |relation| relation }
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
- field_filter_instance = double("field filter instance")
30
- allow(field_filter_instance).to receive(:filter).once
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
- field_filter_instance
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
- expect(relation_mock).to receive(:where) { |relation| relation }
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) { |relation| relation }
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
- expect(filter_instance.test(relation_mock, [:test1, :test2])).to eq(relation_mock)
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(:where) { relation_mock }
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(:where) { relation_mock }
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.0
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-16 00:00:00.000000000 Z
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