filter_factory 0.0.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.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in filter_factory.gemspec
4
+ gemspec
5
+
6
+ gem 'rails', '>= 3.0'
7
+
8
+ group :development do
9
+ gem 'mongoid', '>= 3.0'
10
+ gem 'mysql2'
11
+ end
12
+
13
+ group :test do
14
+ gem 'rspec'
15
+ gem 'database_cleaner'
16
+ gem 'factory_girl'
17
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Hck
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # FilterFactory
2
+
3
+ FilterFactory allows you to easily fetch ActiveRecord/Mongoid models that match specified filters.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'filter_factory'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install filter_factory
18
+
19
+ ## Usage
20
+
21
+ Describe your filter:
22
+
23
+ @filter = FilterFactory.create do
24
+ # filter field definition: field name for ActiveRecord/Mongoid model, filter type
25
+ field :title, :regex
26
+ field :author, :eq
27
+ field :views, :gte
28
+ # ...
29
+ end
30
+
31
+ Render form as you want in your view:
32
+
33
+ <%= form_for @filter, as: :filter do |f| %>
34
+ <div>
35
+ <%= f.label :title %>
36
+ <br/>
37
+ <%= f.text_field %>
38
+ </div>
39
+ <div>
40
+ <%= f.label :author %>
41
+ <br/>
42
+ <%= f.select Author.all.map{|r| [r.name, r.id]} %>
43
+ </div>
44
+ <div>
45
+ <%= f.label :views %>
46
+ <br/>
47
+ <%= f.number_field :views %>
48
+ </div>
49
+ <div class="actions">
50
+ <%= f.submit "Filter" %>
51
+ </div>
52
+ <% end %>
53
+
54
+ Filter your models in controller:
55
+
56
+ @filter.attributes(params[:filter]) # update filter with values supplied from the form
57
+
58
+ @posts = Post.filter(@filter) # fetch records that match specified filters
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'filter_factory/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "filter_factory"
8
+ gem.version = FilterFactory::VERSION
9
+ gem.authors = ["Hck"]
10
+ gem.description = %q{Gem for easy ActiveRecord/Mongoid models filtering}
11
+ gem.summary = %q{FilterFactory allows you to easily fetch ActiveRecord/Mongoid models that match specified filters.}
12
+ gem.homepage = "https://github.com/hck/filter_factory"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,53 @@
1
+ module FilterFactory
2
+ module ActiveRecord
3
+ class Condition < FilterFactory::Condition
4
+ def eq(obj)
5
+ obj.where(field_name => value)
6
+ end
7
+
8
+ def ne(obj)
9
+ obj.where("#{field_name} != ?", value)
10
+ end
11
+
12
+ def lt(obj)
13
+ obj.where("#{field_name} < ?", value)
14
+ end
15
+
16
+ def lte(obj)
17
+ obj.where("#{field_name} <= ?", value)
18
+ end
19
+
20
+ def gt(obj)
21
+ obj.where("#{field_name} > ?", value)
22
+ end
23
+
24
+ def gte(obj)
25
+ obj.where("#{field_name} >= ?", value)
26
+ end
27
+
28
+ def all(obj)
29
+ raise NotImplementedError, "all operator is not available for ActiveRecord"
30
+ end
31
+
32
+ def in(obj)
33
+ obj.where("#{field_name} IN (?)", value)
34
+ end
35
+
36
+ def nin(obj)
37
+ obj.where("#{field_name} NOT IN (?)", value)
38
+ end
39
+
40
+ def regex(obj)
41
+ obj.where("#{field_name} REGEXP ?", value)
42
+ end
43
+
44
+ def exists(obj)
45
+ raise NotImplementedError, "all operator is not available for ActiveRecord"
46
+ end
47
+
48
+ def presents(obj)
49
+ obj.where("(#{field_name} IS NOT NULL) = ?", value)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ module FilterFactory
2
+ module ActiveRecord
3
+ module Filter
4
+ def filter(filter_object)
5
+ conditions = filter_object.filled_fields.map do |field|
6
+ FilterFactory::ActiveRecord::Condition.new(field.name, field.value).method(field.condition)
7
+ end
8
+
9
+ conditions.inject(nil) do |res,condition|
10
+ res ? res.instance_eval(&condition) : instance_eval(&condition)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ ActiveRecord::Base.send(:extend, FilterFactory::ActiveRecord::Filter) if defined?(ActiveRecord::Base)
@@ -0,0 +1,9 @@
1
+ module FilterFactory
2
+ class Condition
3
+ attr_reader :field_name, :value
4
+
5
+ def initialize(field_name, value)
6
+ @field_name, @value = field_name, value
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module FilterFactory
2
+ class Field
3
+ attr_reader :name, :condition, :options
4
+ attr_accessor :value
5
+
6
+ def initialize(name, condition, options = {})
7
+ @name, @condition, @options = name, condition, options
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_model'
2
+
3
+ module FilterFactory
4
+ class Filter
5
+ include ActiveModel::Conversion
6
+ extend ActiveModel::Naming
7
+
8
+ attr_reader :fields
9
+
10
+ def initialize
11
+ @fields = []
12
+ end
13
+
14
+ def attributes
15
+ @fields.inject(HashWithIndifferentAccess.new) do |acc,field|
16
+ acc[field.name] = field.value
17
+ acc
18
+ end
19
+ end
20
+
21
+ def attributes=(attributes = {})
22
+ return unless attributes
23
+ attributes.each do |name, value|
24
+ public_send("#{name}=", value)
25
+ end
26
+ end
27
+
28
+ def filled_fields
29
+ fields.select{|f| !f.value.nil? && f.value != ''}
30
+ end
31
+
32
+ def persisted?
33
+ false
34
+ end
35
+
36
+ private
37
+ def field(name, condition)
38
+ Field.new(name, condition).tap do |field|
39
+ define_singleton_method(name){ field.value }
40
+ define_singleton_method("#{name}="){|val| field.value = val }
41
+
42
+ @fields << field
43
+ end
44
+ end
45
+
46
+ class << self
47
+ def create &block
48
+ new.tap{|filter| filter.instance_eval &block}
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,53 @@
1
+ module FilterFactory
2
+ module Mongoid
3
+ class Condition < FilterFactory::Condition
4
+ def eq(obj)
5
+ obj.where(field_name => value)
6
+ end
7
+
8
+ def ne(obj)
9
+ obj.where(field_name => {'$ne' => value})
10
+ end
11
+
12
+ def lt(obj)
13
+ obj.where(field_name => {'$lt' => value})
14
+ end
15
+
16
+ def lte(obj)
17
+ obj.where(field_name => {'$lte' => value})
18
+ end
19
+
20
+ def gt(obj)
21
+ obj.where(field_name => {'$gt' => value})
22
+ end
23
+
24
+ def gte(obj)
25
+ obj.where(field_name => {'$gte' => value})
26
+ end
27
+
28
+ def all(obj)
29
+ obj.where(field_name => {'$all' => value})
30
+ end
31
+
32
+ def in(obj)
33
+ obj.where(field_name => {'$in' => value})
34
+ end
35
+
36
+ def nin(obj)
37
+ obj.where(field_name => {'$nin' => value})
38
+ end
39
+
40
+ def regex(obj)
41
+ obj.where(field_name => /#{Regexp.escape(value)}/)
42
+ end
43
+
44
+ def exists(obj)
45
+ obj.where(field_name => {'$exists' => value})
46
+ end
47
+
48
+ def presents(obj)
49
+ ['true', '1', 1].include?(value) ? obj.where(field_name => {'$nin' => [nil, '', []]}) : obj.where(field_name => {'$in' => [nil, '', []]})
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ module FilterFactory
2
+ module Mongoid
3
+ module Filter
4
+ def filter(filter_object)
5
+ conditions = filter_object.filled_fields.map do |field|
6
+ FilterFactory::Mongoid::Condition.new(field.name, field.value).method(field.condition)
7
+ end
8
+
9
+ conditions.inject(nil) do |res,condition|
10
+ res ? res.instance_eval(&condition) : instance_eval(&condition)
11
+ end || self
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ if defined?(Mongoid::Document)
18
+ Mongoid::Document.module_eval do
19
+ def self.included(base)
20
+ base.extend FilterFactory::Mongoid::Filter
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module FilterFactory
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,17 @@
1
+ require "filter_factory/version"
2
+
3
+ require "filter_factory/condition"
4
+ require "filter_factory/field"
5
+ require "filter_factory/filter"
6
+
7
+ require "filter_factory/active_record/condition"
8
+ require "filter_factory/active_record/filter"
9
+
10
+ require "filter_factory/mongoid/condition"
11
+ require "filter_factory/mongoid/filter"
12
+
13
+ module FilterFactory
14
+ def self.create &block
15
+ FilterFactory::Filter.create &block
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ FactoryGirl.define do
2
+ factory :mongoid_post, class: MPost do
3
+ sequence(:title) {|n| "post_#{n}"}
4
+ sequence(:author) {|n| "author_#{n}"}
5
+ sequence(:views) {|n| n}
6
+ #views {rand(0..1000)}
7
+ end
8
+
9
+ factory :active_record_post, class: ARPost do
10
+ sequence(:title) {|n| "post_#{n}"}
11
+ sequence(:author) {|n| "author_#{n}"}
12
+ sequence(:views) {|n| n}
13
+ #views {rand(0..1000)}
14
+ end
15
+ end
@@ -0,0 +1,157 @@
1
+ require "spec_helper"
2
+
3
+ describe ARPost do
4
+ before(:each) do
5
+ @posts = FactoryGirl.create_list(:active_record_post, 10)
6
+ end
7
+
8
+ it "should respond to ::filter method" do
9
+ described_class.should respond_to(:filter)
10
+ end
11
+
12
+ it "should execute filter methods chain" do
13
+ filter = FilterFactory.create do
14
+ field :title, :eq
15
+ field :author, :eq
16
+ field :views, :gte
17
+ end
18
+
19
+ sample = @posts.sample
20
+
21
+ filter.title = sample.title
22
+ filter.author = sample.author
23
+
24
+ described_class.filter(filter).to_a.should == [sample]
25
+ end
26
+
27
+ it "should return records with column' values equal to specified value" do
28
+ sample = @posts.sample
29
+
30
+ filter = FilterFactory.create do
31
+ field :id, :eq
32
+ end
33
+ filter.id = sample.id
34
+
35
+ described_class.filter(filter).to_a.should == [sample]
36
+ end
37
+
38
+ it "should return records with column' values not equal specified value" do
39
+ sample = @posts.sample
40
+
41
+ filter = FilterFactory.create do
42
+ field :id, :ne
43
+ end
44
+ filter.id = sample.id
45
+
46
+ described_class.filter(filter).to_a.sort.should == @posts.reject{|p| p.id == sample.id}
47
+ end
48
+
49
+ it "should return records with column' values less than specified value" do
50
+ sample = @posts.sample
51
+
52
+ filter = FilterFactory.create do
53
+ field :views, :lt
54
+ end
55
+ filter.views = sample.views
56
+
57
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views < sample.views}.map(&:id).sort
58
+ end
59
+
60
+ it "should return records with column' values less than or equal to specified value" do
61
+ sample = @posts.sample
62
+
63
+ filter = FilterFactory.create do
64
+ field :views, :lte
65
+ end
66
+ filter.views = sample.views
67
+
68
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views <= sample.views}.map(&:id).sort
69
+ end
70
+
71
+ it "should return records with column' values greater than specified value" do
72
+ sample = @posts.sample
73
+
74
+ filter = FilterFactory.create do
75
+ field :views, :gt
76
+ end
77
+ filter.views = sample.views
78
+
79
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views > sample.views}.map(&:id).sort
80
+ end
81
+
82
+ it "should return records with column' values greater than or equal to specified value" do
83
+ sample = @posts.sample
84
+
85
+ filter = FilterFactory.create do
86
+ field :views, :gte
87
+ end
88
+ filter.views = sample.views
89
+
90
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views >= sample.views}.map(&:id).sort
91
+ end
92
+
93
+ it "should raise NotImplementedError if using 'all' condition" do
94
+ filter = FilterFactory.create do
95
+ field :opts, :all
96
+ end
97
+ filter.opts = [1, 2, 3, 4]
98
+
99
+ expect {described_class.filter(filter)}.to raise_error(NotImplementedError)
100
+ end
101
+
102
+ it "should return records with column' values in specified values" do
103
+ sample = @posts.sample(3)
104
+
105
+ filter = FilterFactory.create do
106
+ field :id, :in
107
+ end
108
+ filter.id = sample.map(&:id)
109
+
110
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
111
+ end
112
+
113
+ it "should return records with column' values not in specified values" do
114
+ sample = @posts.sample(3)
115
+
116
+ filter = FilterFactory.create do
117
+ field :id, :nin
118
+ end
119
+ filter.id = sample.map(&:id)
120
+
121
+ described_class.filter(filter).map(&:id).sort.should == (@posts.map(&:id) - sample.map(&:id)).sort
122
+ end
123
+
124
+ it "should return records with column' values which match the specified regexp" do
125
+ sample = @posts.sample(3)
126
+ sample.each_with_index{|r,i| r.update_attribute(:title, "my_title_#{i}")}
127
+
128
+ filter = FilterFactory.create do
129
+ field :title, :regex
130
+ end
131
+
132
+ filter.title = '_title_'
133
+
134
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
135
+ end
136
+
137
+ it "should raise NotImplementedError if using 'exists' condition" do
138
+ filter = FilterFactory.create do
139
+ field :not_exists, :exists
140
+ end
141
+ filter.not_exists = true
142
+
143
+ expect {described_class.filter(filter)}.to raise_error(NotImplementedError)
144
+ end
145
+
146
+ it "should return records with column' values not nil equal to specified value" do
147
+ sample = @posts.sample(3)
148
+ sample.each{|r| r.update_attribute(:title, nil)}
149
+
150
+ filter = FilterFactory.create do
151
+ field :title, :presents
152
+ end
153
+ filter.title = false
154
+
155
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
156
+ end
157
+ end
@@ -0,0 +1,83 @@
1
+ require "spec_helper"
2
+
3
+ describe FilterFactory::Filter do
4
+ it "should create filter and execute block" do
5
+ test_fields = [[:field1, :eq], [:field2, :eq], [:field3, :eq]]
6
+
7
+ filter = described_class.create do
8
+ test_fields.each do |arr|
9
+ field *arr
10
+ end
11
+ end
12
+
13
+ filter.should be_a(described_class)
14
+
15
+ filter.fields.map{|f| [f.name, f.condition]}.should == test_fields
16
+ end
17
+
18
+ it "should define singleton method for defined field" do
19
+ filter = described_class.create do
20
+ field :name, :eq
21
+ end
22
+
23
+ filter.should respond_to(:name, :'name=')
24
+ end
25
+
26
+ it "should get field value" do
27
+ filter = described_class.create do
28
+ field :name, :eq
29
+ end
30
+
31
+ filter.fields.first.value = "sample name"
32
+ filter.name.should == "sample name"
33
+ end
34
+
35
+ it "should set field value" do
36
+ filter = described_class.create do
37
+ field :name, :eq
38
+ end
39
+
40
+ filter.name = "sample name"
41
+ filter.fields.first.value.should == "sample name"
42
+ end
43
+
44
+ it "should respond_to attributes & attributes= methods" do
45
+ filter = described_class.create do
46
+ field :name, :eq
47
+ end
48
+
49
+ filter.should respond_to(:attributes, :attributes=)
50
+ end
51
+
52
+ it "should return valid attributes" do
53
+ filter = described_class.create do
54
+ field :name, :eq
55
+ field :surname, :regex
56
+ end
57
+ filter.name = "test name"
58
+
59
+ filter.attributes.should == HashWithIndifferentAccess.new({name: "test name", surname: nil})
60
+ end
61
+
62
+ it "should fill filter values from hash" do
63
+ filter = described_class.create do
64
+ field :name, :eq
65
+ field :surname, :regex
66
+ end
67
+
68
+ attributes = {name: "my test name", surname: "surname here"}
69
+ filter.attributes = attributes
70
+ filter.attributes.should == HashWithIndifferentAccess.new(attributes)
71
+ end
72
+
73
+ #describe "#conditions" do
74
+ # it "should return result of query method for each of the condition as a Method object" do
75
+ # filter = described_class.create do
76
+ # field :name, :eq
77
+ # end
78
+ #
79
+ # filter.name = "sample name"
80
+ # filter.conditions.first.should be_a(Method)
81
+ # end
82
+ #end
83
+ end
@@ -0,0 +1,152 @@
1
+ require "spec_helper"
2
+
3
+ describe MPost do
4
+ before(:each) do
5
+ @posts = FactoryGirl.create_list(:mongoid_post, 10)
6
+ end
7
+
8
+ it "should respond to ::filter method" do
9
+ described_class.should respond_to(:filter)
10
+ end
11
+
12
+ it "should execute filter methods chain" do
13
+ sample = @posts.sample
14
+
15
+ filter = FilterFactory.create do
16
+ field :title, :eq
17
+ field :author, :eq
18
+ field :views, :gte
19
+ end
20
+
21
+ filter.title = sample.title
22
+ filter.author = sample.author
23
+
24
+ described_class.filter(filter).to_a.should == [sample]
25
+ end
26
+
27
+ it "should return records with column' values equal to specified value" do
28
+ sample = @posts.sample
29
+
30
+ filter = FilterFactory.create do
31
+ field :id, :eq
32
+ end
33
+ filter.id = sample.id
34
+
35
+ described_class.filter(filter).to_a.should == [sample]
36
+ end
37
+
38
+ it "should return records with column' values not equal specified value" do
39
+ sample = @posts.sample
40
+
41
+ filter = FilterFactory.create do
42
+ field :id, :ne
43
+ end
44
+ filter.id = sample.id
45
+
46
+ described_class.filter(filter).to_a.sort.should == @posts.reject{|p| p.id == sample.id}
47
+ end
48
+
49
+ it "should return records with column' values less than specified value" do
50
+ sample = @posts.sample
51
+
52
+ filter = FilterFactory.create do
53
+ field :views, :lt
54
+ end
55
+ filter.views = sample.views
56
+
57
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views < sample.views}.map(&:id).sort
58
+ end
59
+
60
+ it "should return records with column' values less than or equal to specified value" do
61
+ sample = @posts.sample
62
+
63
+ filter = FilterFactory.create do
64
+ field :views, :lte
65
+ end
66
+ filter.views = sample.views
67
+
68
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views <= sample.views}.map(&:id).sort
69
+ end
70
+
71
+ it "should return records with column' values greater than specified value" do
72
+ sample = @posts.sample
73
+
74
+ filter = FilterFactory.create do
75
+ field :views, :gt
76
+ end
77
+ filter.views = sample.views
78
+
79
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views > sample.views}.map(&:id).sort
80
+ end
81
+
82
+ it "should return records with column' values greater than or equal to specified value" do
83
+ sample = @posts.sample
84
+
85
+ filter = FilterFactory.create do
86
+ field :views, :gte
87
+ end
88
+ filter.views = sample.views
89
+
90
+ described_class.filter(filter).map(&:id).sort.should == @posts.select{|p| p.views >= sample.views}.map(&:id).sort
91
+ end
92
+
93
+ it "should return records with column' values all equal to specified value" do
94
+ sample = @posts.sample(2)
95
+ sample.each{|r| r.update_attribute(:opts, [1, 2, 3, 4])}
96
+
97
+ filter = FilterFactory.create do
98
+ field :opts, :all
99
+ end
100
+ filter.opts = [1, 2, 3, 4]
101
+
102
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
103
+ end
104
+
105
+ it "should return records with column' values in specified values" do
106
+ sample = @posts.sample(3)
107
+
108
+ filter = FilterFactory.create do
109
+ field :id, :in
110
+ end
111
+ filter.id = sample.map(&:id)
112
+
113
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
114
+ end
115
+
116
+ it "should return records with column' values not in specified values" do
117
+ sample = @posts.sample(3)
118
+
119
+ filter = FilterFactory.create do
120
+ field :id, :nin
121
+ end
122
+ filter.id = sample.map(&:id)
123
+
124
+ described_class.filter(filter).map(&:id).sort.should == (@posts.map(&:id) - sample.map(&:id)).sort
125
+ end
126
+
127
+ it "should return records with column' values which match the specified regexp" do
128
+ sample = @posts.sample(3)
129
+ sample.each_with_index{|r,i| r.update_attribute(:title, "my_title_#{i}")}
130
+
131
+ filter = FilterFactory.create do
132
+ field :title, :regex
133
+ end
134
+
135
+ filter.title = '_title_'
136
+
137
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
138
+ end
139
+
140
+ it "should return records with existing column' values" do
141
+ sample = @posts.sample(3)
142
+ sample.each{|r| r.update_attribute(:not_exists, rand(0..25))}
143
+
144
+ filter = FilterFactory.create do
145
+ field :not_exists, :exists
146
+ end
147
+
148
+ filter.not_exists = true
149
+
150
+ described_class.filter(filter).map(&:id).sort.should == sample.map(&:id).sort
151
+ end
152
+ end
@@ -0,0 +1,2 @@
1
+ class ARPost < ActiveRecord::Base
2
+ end
@@ -0,0 +1,9 @@
1
+ class MPost
2
+ include Mongoid::Document
3
+
4
+ field :title, type: String
5
+ field :author, type: String
6
+ field :views, type: Integer
7
+ field :opts, type: Array
8
+ field :not_exists, type: Boolean
9
+ end
@@ -0,0 +1,57 @@
1
+ MODELS = File.join(File.dirname(__FILE__), 'models')
2
+
3
+ require 'rubygems'
4
+
5
+ require 'mongoid'
6
+ require 'active_record'
7
+ require 'database_cleaner'
8
+ require 'factory_girl'
9
+
10
+ require 'filter_factory'
11
+
12
+ Dir["#{MODELS}/*.rb"].each { |f| require f }
13
+
14
+ Mongoid.configure do |config|
15
+ config.connect_to 'mongoid_filter_factory_test'
16
+ end
17
+ #Mongoid.logger = Logger.new($stdout)
18
+ #Moped.logger = Logger.new($stdout)
19
+
20
+ ActiveRecord::Base.establish_connection(
21
+ adapter: "mysql2",
22
+ database: "active_record_filter_factory_test"
23
+ )
24
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS ar_posts")
25
+ ActiveRecord::Base.connection.create_table(:ar_posts) do |t|
26
+ t.string :title
27
+ t.string :author
28
+ t.integer :views
29
+ end
30
+ #ActiveRecord::Base.logger = Logger.new($stdout)
31
+ #ActiveRecord::Base.logger.level = Logger::DEBUG
32
+
33
+ FactoryGirl.definition_file_paths = [File.join(File.dirname(__FILE__), 'factories')]
34
+ FactoryGirl.find_definitions
35
+
36
+ RSpec.configure do |config|
37
+ config.mock_with :rspec
38
+ config.color_enabled = true
39
+
40
+ config.before(:suite) do
41
+ mongoid = DatabaseCleaner[:mongoid]
42
+ mongoid.strategy = :truncation
43
+ mongoid.clean_with(:truncation)
44
+
45
+ active_record = DatabaseCleaner[:active_record]
46
+ active_record.strategy = :truncation
47
+ active_record.clean_with(:truncation)
48
+ end
49
+
50
+ config.before(:each) do
51
+ DatabaseCleaner.start
52
+ end
53
+
54
+ config.after(:each) do
55
+ DatabaseCleaner.clean
56
+ end
57
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: filter_factory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Hck
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Gem for easy ActiveRecord/Mongoid models filtering
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - Gemfile
22
+ - LICENSE.txt
23
+ - README.md
24
+ - Rakefile
25
+ - filter_factory.gemspec
26
+ - lib/filter_factory.rb
27
+ - lib/filter_factory/active_record/condition.rb
28
+ - lib/filter_factory/active_record/filter.rb
29
+ - lib/filter_factory/condition.rb
30
+ - lib/filter_factory/field.rb
31
+ - lib/filter_factory/filter.rb
32
+ - lib/filter_factory/mongoid/condition.rb
33
+ - lib/filter_factory/mongoid/filter.rb
34
+ - lib/filter_factory/version.rb
35
+ - spec/factories/factories.rb
36
+ - spec/filter_factory/active_record/model_spec.rb
37
+ - spec/filter_factory/filter_spec.rb
38
+ - spec/filter_factory/mongoid/model_spec.rb
39
+ - spec/models/ar_post.rb
40
+ - spec/models/m_post.rb
41
+ - spec/spec_helper.rb
42
+ homepage: https://github.com/hck/filter_factory
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 1.8.23
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: FilterFactory allows you to easily fetch ActiveRecord/Mongoid models that
66
+ match specified filters.
67
+ test_files:
68
+ - spec/factories/factories.rb
69
+ - spec/filter_factory/active_record/model_spec.rb
70
+ - spec/filter_factory/filter_spec.rb
71
+ - spec/filter_factory/mongoid/model_spec.rb
72
+ - spec/models/ar_post.rb
73
+ - spec/models/m_post.rb
74
+ - spec/spec_helper.rb