easy_filters 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c4d6be28e25fe3be62cf50ab45d044a7ca7083d
4
+ data.tar.gz: e221ccf98fa4c6fcc69cb60786997af1d5fb3712
5
+ SHA512:
6
+ metadata.gz: 0c24d10fbf0d42b5079a7e843ae0b4d98cb13c64e7e28cf66d4c6ee549f058690adf1492a88a341517368e28a9f5e9e8689690f9a651db873831576daab4f0a6
7
+ data.tar.gz: 946460bf9331eebe0578d072636168003598afdb9db9358629e043c37a2dc76a98f0fa1df5ef9c73e120f7398aa23708f1587af72f20ce10e4cc7d2c13e6d7ad
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in easy_filters.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 German Olle
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,82 @@
1
+ # EasyFilters
2
+
3
+ This gem provides a simple API for defining dynamic persistent(in session) filters based on active record models.
4
+ This was extracted from el_dia_backend
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+
12
+ gem 'easy_filters'
13
+
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ ```bash
19
+
20
+ $ bundle
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ EasyFilters expects you to define the following methods:
26
+
27
+ ```ruby
28
+ class ArticlesFilter < ModelFilter
29
+
30
+ # Default values for this filter.
31
+ def self.defaults
32
+ { body: nil, date_from: nil, date_to: nil }
33
+ end
34
+
35
+ # Model class to be filtered.
36
+ def model
37
+ Article
38
+ end
39
+ end
40
+
41
+ ```
42
+
43
+ * __defaults__: defines the fields that will be used for filtering and its defaults values
44
+ * __model__: returns the target class to be filtered
45
+
46
+ ### Customizing filtering strategy
47
+
48
+ For defining the parts of the query that will filter each each field,
49
+ define a method named `filter_by_#{field_name}`.
50
+ The field __must__ be present in the defaults array.
51
+
52
+ Each `filter_by_*` method receives 2 params:
53
+ * __scope__: The actual query.
54
+ * __value__: The value for the current field
55
+
56
+ For example:
57
+
58
+ ```ruby
59
+ class ArticlesFilter < ModelFilter
60
+
61
+ #(...) previously defined methods
62
+
63
+ # Custom filter method for :body field.
64
+ def filter_by_body(scope, value)
65
+ matcher = "%#{value}%"
66
+ scope.where('body like ? OR body like ?', matcher, matcher)
67
+ end
68
+
69
+ # The following 2 filter_by builds an from/to/between date filter:
70
+
71
+ # Custom filter method for :date_from field.
72
+ def filter_by_date_from(scope, value)
73
+ scope.joins(:editions).where('editions.date >= ?', Date.parse(value))
74
+ end
75
+
76
+ # Custom filter method for :date_to field.
77
+ def filter_by_date_to(scope, value)
78
+ scope.joins(:editions).where('editions.date <= ?', Date.parse(value))
79
+ end
80
+ end
81
+
82
+ ```
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'rake/testtask'
2
+ require 'active_record'
3
+ require 'sqlite3'
4
+
5
+ desc 'Create table structure for testing'
6
+ task :migrate do
7
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'db/easy_filters_test.sqlite3')
8
+ ActiveRecord::Schema.define do
9
+ create_table :articles do |t|
10
+ t.string :slug, null: false, index: true
11
+ t.text :heading
12
+ t.text :title, null: false
13
+ t.boolean :show_time, null: false, default: false
14
+ t.date :date
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+ end
20
+
21
+ desc 'Run tests'
22
+ Rake::TestTask.new :test do |t|
23
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'db/easy_filters_test.sqlite3')
24
+
25
+ Rake::Task[:migrate].invoke unless ActiveRecord::Base.connection.table_exists? 'articles'
26
+
27
+ t.libs << 'spec'
28
+ t.pattern = 'spec/**/*_spec.rb'
29
+ end
30
+
31
+ task default: :test
Binary file
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'easy_filters/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "easy_filters"
9
+ spec.version = EasyFilters::VERSION
10
+ spec.authors = ["German Olle"]
11
+ spec.email = ["golle@cespi.unlp.edu.ar"]
12
+ spec.summary = "This gem implement a base model filter to declare your owns filters writing a single file"
13
+ spec.description = "Define a model class, allowing declare a subclass of this and implement simple methods to filter each field model"
14
+ spec.homepage = "http://rubygems.org/gems/easy_filters"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake", "~> 0"
24
+ spec.add_development_dependency "sqlite3", "~> 0"
25
+
26
+ spec.add_dependency 'activerecord', "~> 4.0"
27
+ end
@@ -0,0 +1,2 @@
1
+ require "easy_filters/filter"
2
+ require "easy_filters/model_filter"
@@ -0,0 +1,148 @@
1
+ module EasyFilters
2
+ # Base class for any object used for keeping filtering logic + criteria together.
3
+ #
4
+ # This class provides the following functionality out-of-the-box:
5
+ #
6
+ # - Automatic values sanitizing: The values passed to the #initialize method
7
+ # will be fed into #sanitize and the result of that process will be used for
8
+ # setting the filter values.
9
+ # - Hash-like accessors: Any value for the filters can be get/set via []/[]=,
10
+ # just like Hashes.
11
+ #
12
+ # For examples, please:
13
+ # @see ArticlesFilter
14
+ # @see SupplementFilter
15
+ class Filter
16
+
17
+ # Default values. This method should be overridden
18
+ # when in need to specify particular defaults for a
19
+ # subclass.
20
+ def self.defaults
21
+ {}
22
+ end
23
+
24
+ # Global key that will contain the values for any filter class
25
+ # inside the store or the request values source.
26
+ # In extension, the store options should be structured
27
+ # like this:
28
+ # {
29
+ # :"#{Filter.global_key}" => {
30
+ # :"#{@filter.key}" => {
31
+ # :value => 'for a filter field'
32
+ # }
33
+ # }
34
+ # }
35
+ def self.global_key
36
+ :filter
37
+ end
38
+
39
+ # Particular key that will contain the values for this specific
40
+ # filter class in the store/request values source - under the
41
+ # Filter#global_key main key.
42
+ # In extension, the store options should be structured
43
+ # like this:
44
+ # {
45
+ # :"#{Filter.global_key}" => {
46
+ # :"#{@filter.key}" => {
47
+ # :value => 'for a filter field'
48
+ # }
49
+ # }
50
+ # }
51
+ def self.key
52
+ self.name.to_sym
53
+ end
54
+
55
+ # Initialize a new filter with the given options.
56
+ def initialize(options = {})
57
+ @options = { values: nil, store: nil, persist: false }.merge options
58
+
59
+ # This is the order of precedence:
60
+ # values => store => defaults
61
+ actual = options[:values]
62
+ store = options[:store]
63
+
64
+ source = self.class.defaults
65
+
66
+ source = store[self.class.global_key][key] if store && store[self.class.global_key] && store[self.class.global_key][key]
67
+ source = actual if actual
68
+
69
+ self.values = sanitize source
70
+
71
+ self
72
+ end
73
+
74
+ # Conditionally clean up some values after the initialization is finished
75
+ # Note:
76
+ # These method have sense when the subclasses uses it,
77
+ # Filter class will not allows to pass any value
78
+ # due that the defaults is an empty hash so the valid keys is an empty array
79
+ def sanitize(values)
80
+ valid_keys = self.class.defaults.keys
81
+ values.inject(self.class.defaults) do |carry, (k, v)|
82
+ carry[k] = v if valid_keys.include?(k) && !v.blank?
83
+ carry
84
+ end
85
+ end
86
+
87
+ # Instance method used for convenience. Just a wrapper for the
88
+ # class method #key.
89
+ def key
90
+ self.class.key
91
+ end
92
+
93
+ # Filter field value accessor. Provides a Hash-like API for
94
+ # getting the values set to the different fields of this filter.
95
+ # Will return the value set for :key or nil.
96
+ def [] key
97
+ values[key] if values.has_key? key
98
+ end
99
+
100
+ # Filter field value writer. Provides a Hash-like API for
101
+ # setting the values of the filter fields.
102
+ def []=(key, value)
103
+ values[key] = value
104
+ end
105
+
106
+ # Answer whether any filter values have been applied. Will return
107
+ # true if the current values differ from the default ones.
108
+ def any?
109
+ self.class.defaults != self.values
110
+ end
111
+
112
+ # Gets the values for this filter.
113
+ def values
114
+ @values
115
+ end
116
+
117
+ # Sets the values for this filter to :new_values.
118
+ # Will persist if the :persist option was set to true when creating
119
+ # this object and a valid store has been provided.
120
+ def values=(new_values)
121
+ @values = new_values
122
+
123
+ # Define getters for each of the new_values
124
+ new_values.each do |key, value|
125
+ self.class.send(:define_method, key, proc { self[key] }) unless self.respond_to? key
126
+ end
127
+
128
+ self.persist! @options[:store] if @options[:store] && @options[:persist]
129
+ end
130
+
131
+ # Persist the current values to the given :store.
132
+ def persist!(store)
133
+ store[self.class.global_key] ||= {}
134
+ store[self.class.global_key][self.class.key] = self.values
135
+ end
136
+
137
+ # Clear the values of the filters - set them to the defaults.
138
+ def clear!
139
+ self.values = self.class.defaults
140
+ end
141
+
142
+ # Get all the matching records to the current filter criteria.
143
+ # This method must be implemented in subclasses.
144
+ def all
145
+ throw NotImplementedError
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,75 @@
1
+ module EasyFilters
2
+ # Base class for ActiveRecord-bound filter classes.
3
+ # Subclasses must implement the #model method and optionally add
4
+ # custom filtering methods, as explained below in the #apply_to method.
5
+ class ModelFilter < Filter
6
+ # Get the model class to which the filters will be applied.
7
+ # This method must be overridden in subclasses.
8
+ def model
9
+ raise NotImplementedError
10
+ end
11
+
12
+ # Get all the matching records to the current filter criteria.
13
+ def all
14
+ matches = model.send(scope)
15
+ matches = apply_to matches
16
+ end
17
+
18
+ # Get the scope that will start the filter criteria as a symbol.
19
+ # The default scope is :all.
20
+ def scope
21
+ :all
22
+ end
23
+
24
+ # Applies the filter criteria specified for the different fields to :matches,
25
+ # an ActiveRecordRelation which should start by matching all the "filterable"
26
+ # records.
27
+ #
28
+ # Each field will be processed in the following way:
29
+ # 1. Check if self responds to a custom filter method of the form: "filter_by_<FIELD_NAME>". If it does,
30
+ # delegate the filtering of records by that field to the method. Such a method must return the updated
31
+ # ActiveRecordRelation.
32
+ # For instance, if the field name is "slug", its custom filter method will be named "filter_by_slug":
33
+ #
34
+ # def filter_by_slug(partial, value)
35
+ # partial.where(slug: value)
36
+ # end
37
+ #
38
+ # 2. If no custom filter method is available for the field, check for a default filter method by the class
39
+ # of the value. Supported classes out-of-the-box are:
40
+ #
41
+ # - String: Will search with a 'like "%value%"'.
42
+ #
43
+ # 3. Otherwise, leave the logic up to ActiveRecord. Will add a where constraint like follows:
44
+ #
45
+ # partial.where(field.to_sym => value)
46
+ #
47
+ def apply_to(matches)
48
+ values.inject(matches) do |partial, pair|
49
+ field, value = pair
50
+ unless value.blank?
51
+ type = value.class.name.downcase
52
+ custom_filter_method = "filter_by_#{field}"
53
+ default_filter_method = "filter_#{type}_field"
54
+ if self.respond_to? custom_filter_method
55
+ # Custom filtering
56
+ partial = self.send custom_filter_method, partial, value
57
+ elsif self.respond_to? default_filter_method
58
+ # Default method filtering
59
+ partial = self.send default_filter_method, partial, field, value
60
+ else
61
+ # Leave it up to AR and its magic
62
+ partial = partial.where(field.to_sym => value)
63
+ end
64
+ end
65
+
66
+ partial
67
+ end
68
+ end
69
+
70
+ # Filters String fields using LIKE.
71
+ def filter_string_field(partial, field, value)
72
+ partial.where("#{field} like ?", "%#{value}%")
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ module EasyFilters
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,143 @@
1
+ require 'minitest_helper'
2
+
3
+ module EasyFilters
4
+ describe Filter do
5
+ before do
6
+ @filter = Filter.new
7
+ end
8
+
9
+ after do
10
+ @filter.clear!
11
+ end
12
+
13
+ it ":defaults should return a hash with default filter values" do
14
+ assert_instance_of Hash, Filter.defaults, ':defaults does not return a Hash'
15
+ assert Filter.defaults.empty?, ':defaults does not return an empty set of defaults values'
16
+ end
17
+
18
+ it ":key should return a representative symbol" do
19
+ assert_same 'EasyFilters::Filter'.to_sym, Filter.key, ':key does not return a representative symbol'
20
+ end
21
+
22
+ it ":[]= should set values under :key key" do
23
+ @filter[:name] = 'test value'
24
+
25
+ assert_equal 'test value', @filter[:name], ':[]= does not set the passed in :value at :key'
26
+ end
27
+
28
+ it ":[] should access the values under :key key" do
29
+ @filter[:surname] = 'some test value'
30
+
31
+ assert_equal 'some test value', @filter[:surname], ':[] does not access previously-set values'
32
+ end
33
+
34
+ it ":[] should return nil if :key is not set" do
35
+ assert @filter[:non_existing_key].nil?, ':[] does not return nil? for non-existant keys'
36
+ end
37
+
38
+ it ":any? should return false if there's no filter applied" do
39
+ assert !@filter.any?, ':any? returns true when no filters are applied'
40
+ end
41
+
42
+ it ":any? should return true if there's a filter applied" do
43
+ @filter[:some] = 'value'
44
+ assert @filter.any?, ':any? returns false when there are filters applied'
45
+ end
46
+
47
+ it ":values should return a hash representation of the values applied to the filter" do
48
+ @filter[:some] = 'value'
49
+ @filter[:test] = 'data'
50
+
51
+ expected = { some: 'value', test: 'data' }
52
+
53
+ assert_equal expected, @filter.values, ':values does not return the values applied to the filter'
54
+ end
55
+
56
+ it ":persist! should store filter values in the provided store" do
57
+ session_mock = {}
58
+ @filter[:name] = 'value'
59
+ @filter.persist! session_mock
60
+
61
+ expected = { name: 'value' }
62
+
63
+ assert session_mock.has_key?(Filter.global_key), ':persist! does not create a namespaced hash of values in the store'
64
+ assert session_mock[Filter.global_key].has_key?(Filter.key), ':persist! does not add specific values for the unique key of the filters class'
65
+ assert_equal @filter.values, session_mock[Filter.global_key][Filter.key]
66
+ end
67
+
68
+ it ":initialize should not take values from store if these are invalid" do
69
+ expected = {}
70
+ session_mock = { filter: { Filter: { invalid_key: 'no valid value' } } }
71
+
72
+ @filter = Filter.new store: session_mock
73
+
74
+ assert_equal expected, @filter.values, ':initialize taked the values from the store'
75
+ end
76
+
77
+ it ":initialize should take values from defaults if the store doesn't have any values" do
78
+ session_mock = nil
79
+
80
+ @filter = Filter.new store: session_mock
81
+
82
+ assert_equal Filter.defaults, @filter.values, ':initialize did not take the values from the defaults'
83
+ end
84
+
85
+ it ":initialize should not prioritize passed in values over any other value source if these are invalid" do
86
+ expected = {}
87
+ value = { invalid_key: 'invalid value' }
88
+ session_mock = { filter: { Filter: {} } }
89
+
90
+ @filter = Filter.new store: session_mock, values: value
91
+
92
+ assert_equal expected, @filter.values, ':initialize taked the passed invalid values'
93
+ end
94
+
95
+ it ":initialize should not persist values by default even when a :store option is provided" do
96
+ store_mock = {}
97
+ expected = {}
98
+
99
+ @filter = Filter.new values: { this_value: 'will not be persisted' }, store: store_mock
100
+
101
+ assert_equal expected, store_mock, ':initialize persists values by default'
102
+ end
103
+
104
+ it ":initialize should not persist values if a valid store is provided and instructed to but the passed value is invalid" do
105
+ store_mock = {}
106
+ expected = {}
107
+ value = { look_me: "I will fail" }
108
+
109
+ @filter = Filter.new values: value, store: store_mock, persist: true
110
+
111
+ assert store_mock.has_key?(Filter.global_key), 'The values were not persisted as expected in the store: missing global filter namespace'
112
+ assert store_mock[Filter.global_key].has_key?(Filter.key), 'The values were not persisted as expected in the store: missing specific filter key'
113
+ assert_equal expected, store_mock[Filter.global_key][Filter.key]
114
+ end
115
+
116
+ it ":clear! should reset the filter values to :defaults" do
117
+ @filter = Filter.new values: { other: 'values' }
118
+ @filter.clear!
119
+
120
+ assert_equal Filter.defaults, @filter.values, 'Filter values were not reset to the defaults'
121
+ end
122
+
123
+ it ":clear! should persist the reset filters if filter was created with persist option set to true" do
124
+ store_mock = { filter: { :'EasyFilters::Filter' => { look_ma: "I'm gonna disappear!" } } }
125
+
126
+ @filter = Filter.new store: store_mock, persist: true
127
+ @filter.clear!
128
+
129
+ assert_equal Filter.defaults, store_mock[:filter][:'EasyFilters::Filter'], 'Filter values reset was not persisted'
130
+ end
131
+
132
+ it ":clear! shouldn't persist the reset filters if filter was created with persist option set to false" do
133
+ expected = { look_ma: "I'm gonna disappear!" }
134
+ store_mock = { filter: { Filter: expected } }
135
+
136
+ @filter = Filter.new store: store_mock, persist: false
137
+ @filter.clear!
138
+
139
+ assert_equal Filter.defaults, @filter.values, 'Filter values were not reset'
140
+ assert_equal expected, store_mock[:filter][:Filter], 'Filter values reset was not persisted'
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,17 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'bundler'
4
+ Bundler.require :default, ENV['RACK_ENV'].to_sym
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest/pride'
8
+ require 'active_record'
9
+ require 'sqlite3'
10
+
11
+ ActiveRecord::Base.establish_connection({
12
+ adapter: 'sqlite3',
13
+ database: 'db/easy_filters_test.sqlite3'
14
+ })
15
+
16
+ class Article < ActiveRecord::Base
17
+ end
@@ -0,0 +1,102 @@
1
+ require 'minitest_helper'
2
+
3
+ module EasyFilters
4
+ describe ModelFilter do
5
+ def create_article(params = {})
6
+ defaults = { slug: 'title-one', heading: 'heading one', title: 'title one', show_time: false, date: '2013-01-04' }
7
+ Article.create! defaults.merge params
8
+ end
9
+
10
+ before do
11
+ @filter = ModelFilter.new
12
+ # Overriding #model method in order to make the class testable
13
+ class << @filter
14
+ def model
15
+ Article
16
+ end
17
+ end
18
+ end
19
+
20
+ after do
21
+ @filter.clear!
22
+ Article.delete_all
23
+ end
24
+
25
+ it ":model should fail because there is no default model attached to the filter" do
26
+ filter = ModelFilter.new
27
+
28
+ assert_raises NotImplementedError, 'The base class has a default model attached to it' do
29
+ filter.model
30
+ end
31
+ end
32
+
33
+ it ":all should return all records by default" do
34
+ assert_equal Article.all, @filter.all, 'Some records were left out by a vanilla :all'
35
+ end
36
+
37
+ it ":all should apply the filters when it values for them provided" do
38
+ create_article
39
+ @filter[:slug] = 'one'
40
+
41
+ assert_equal 1, @filter.all.count, ':all did not apply the filters specified'
42
+ end
43
+
44
+ it ":apply_to should not modify the matches ARRelation if no non-nil values are set" do
45
+ @filter[:slug] = nil
46
+ @filter[:title] = nil
47
+
48
+ arr = Article.all
49
+
50
+ assert_same arr, @filter.apply_to(arr), 'The ActiveRecordRelation passed in to :apply_to is modified even with nil values'
51
+ end
52
+
53
+ it ":apply_to should use custom filter methods when they are available" do
54
+ @filter[:heading] = 'heading'
55
+
56
+ class << @filter
57
+ def filter_by_heading(partial, value)
58
+ partial.where(heading: "not #{value}")
59
+ end
60
+ end
61
+
62
+ arr = Article.all
63
+
64
+ assert_equal 0, @filter.apply_to(arr).count, 'The filter was not applied'
65
+ end
66
+
67
+ it ":apply_to should filter string values using a LIKE query by default" do
68
+ # This scenario should only match one title: 'title one'
69
+ create_article(title: 'title one')
70
+ create_article(title: 'title two')
71
+ @filter[:title] = 'one'
72
+ arr = Article.all
73
+
74
+ assert_equal 1, @filter.apply_to(arr).count, 'The filter was not applied in the expected way'
75
+
76
+ @filter.clear!
77
+
78
+ # This scenario should match both of the titles: 'title one' and 'title two'
79
+ @filter[:title] = 'title'
80
+ assert_equal 2, @filter.apply_to(arr).count, 'The filter was not applied in the expected way'
81
+ end
82
+
83
+ it ":apply_to sould use a default filtering strategy when using Date values" do
84
+ create_article(date: '2013-01-01')
85
+ create_article(date: '2013-02-01', show_time: true)
86
+
87
+ # DateTime
88
+ @filter[:date] = '2013-01-01'
89
+ assert_equal 1, @filter.apply_to(Article.all).count, 'A DateTime value is not handled correctly'
90
+ end
91
+
92
+
93
+ it ":apply_to sould use a default filtering strategy when using Boolean values" do
94
+ create_article(date: '2013-01-01')
95
+ create_article(date: '2013-02-01', show_time: true)
96
+
97
+ # Boolean
98
+ @filter[:show_time] = true
99
+ assert_equal 1, @filter.apply_to(Article.all).count, 'A Boolean value is not handled correctly'
100
+ end
101
+ end
102
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easy_filters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - German Olle
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ description: Define a model class, allowing declare a subclass of this and implement
70
+ simple methods to filter each field model
71
+ email:
72
+ - golle@cespi.unlp.edu.ar
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - db/easy_filters_test.sqlite3
83
+ - easy_filters.gemspec
84
+ - lib/easy_filters.rb
85
+ - lib/easy_filters/filter.rb
86
+ - lib/easy_filters/model_filter.rb
87
+ - lib/easy_filters/version.rb
88
+ - spec/filter_spec.rb
89
+ - spec/minitest_helper.rb
90
+ - spec/model_filter_spec.rb
91
+ homepage: http://rubygems.org/gems/easy_filters
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.2.2
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: This gem implement a base model filter to declare your owns filters writing
115
+ a single file
116
+ test_files:
117
+ - spec/filter_spec.rb
118
+ - spec/minitest_helper.rb
119
+ - spec/model_filter_spec.rb