easy_filters 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.
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