filter_factory 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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