acts_as_filterable 0.1.4 → 0.2.0
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/README.rdoc +1 -1
- data/Rakefile +3 -4
- data/VERSION.yml +2 -2
- data/acts_as_filterable.gemspec +9 -5
- data/lib/acts_as_filterable/base.rb +20 -32
- data/lib/acts_as_filterable.rb +0 -1
- data/test/acts_as_filterable_integration_test.rb +11 -27
- data/test/filter_test.rb +129 -0
- data/test/test_helper.rb +2 -1
- metadata +6 -4
data/README.rdoc
CHANGED
@@ -11,7 +11,7 @@ I'd like to expand the ruleset moving forward to support different schemes like
|
|
11
11
|
|
12
12
|
== Install as a gem:
|
13
13
|
|
14
|
-
config.gem "
|
14
|
+
config.gem "acts_as_filterable", :source => "http://gemcutter.org"
|
15
15
|
|
16
16
|
== To apply to fields on a model, add the following inside the class body:
|
17
17
|
|
data/Rakefile
CHANGED
@@ -1,19 +1,18 @@
|
|
1
|
-
require "rubygems"
|
2
1
|
require "rake"
|
3
2
|
|
4
3
|
begin
|
5
4
|
require "jeweler"
|
6
5
|
Jeweler::Tasks.new do |gem|
|
7
6
|
gem.name = "acts_as_filterable"
|
8
|
-
gem.summary = %Q{
|
7
|
+
gem.summary = %Q{Filter attributes and stuff.}
|
9
8
|
gem.email = "rob.ares@gmail.com"
|
10
9
|
gem.homepage = "http://github.com/rares/acts_as_filterable"
|
11
10
|
gem.authors = ["Rob Ares"]
|
12
11
|
|
13
12
|
gem.add_dependency("activerecord", ">= 1.15.0")
|
14
13
|
gem.add_runtime_dependency("activesupport", ">= 1.4.4")
|
15
|
-
gem.add_development_dependency("Shoulda")
|
16
|
-
gem.add_development_dependency("matchy")
|
14
|
+
gem.add_development_dependency("Shoulda", ">= 0")
|
15
|
+
gem.add_development_dependency("matchy", ">= 0")
|
17
16
|
end
|
18
17
|
rescue LoadError
|
19
18
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
data/VERSION.yml
CHANGED
data/acts_as_filterable.gemspec
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{acts_as_filterable}
|
5
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
11
|
s.authors = ["Rob Ares"]
|
9
|
-
s.date = %q{2009-
|
12
|
+
s.date = %q{2009-10-29}
|
10
13
|
s.email = %q{rob.ares@gmail.com}
|
11
14
|
s.extra_rdoc_files = [
|
12
15
|
"LICENSE",
|
@@ -25,16 +28,17 @@ Gem::Specification.new do |s|
|
|
25
28
|
"lib/acts_as_filterable/base.rb",
|
26
29
|
"rails/init.rb",
|
27
30
|
"test/acts_as_filterable_integration_test.rb",
|
31
|
+
"test/filter_test.rb",
|
28
32
|
"test/test_helper.rb"
|
29
33
|
]
|
30
|
-
s.has_rdoc = true
|
31
34
|
s.homepage = %q{http://github.com/rares/acts_as_filterable}
|
32
35
|
s.rdoc_options = ["--charset=UTF-8"]
|
33
36
|
s.require_paths = ["lib"]
|
34
|
-
s.rubygems_version = %q{1.3.
|
35
|
-
s.summary = %q{
|
37
|
+
s.rubygems_version = %q{1.3.5}
|
38
|
+
s.summary = %q{Filter attributes and stuff.}
|
36
39
|
s.test_files = [
|
37
40
|
"test/acts_as_filterable_integration_test.rb",
|
41
|
+
"test/filter_test.rb",
|
38
42
|
"test/test_helper.rb"
|
39
43
|
]
|
40
44
|
|
@@ -1,5 +1,12 @@
|
|
1
1
|
module ActsAsFilterable
|
2
2
|
|
3
|
+
Filters = returning Hash.new([]) do |f|
|
4
|
+
f[:digits] = lambda { |attr| attr.gsub!(/[^\d]*/, "") }
|
5
|
+
f[:lowercase] = lambda { |attr| attr.downcase! }
|
6
|
+
f[:uppercase] = lambda { |attr| attr.upcase! }
|
7
|
+
f[:whitespace] = lambda { |attr| attr.gsub!(/\s+/, " "); attr.strip! }
|
8
|
+
end.freeze
|
9
|
+
|
3
10
|
module ActiveRecordExt
|
4
11
|
|
5
12
|
module Base
|
@@ -9,57 +16,38 @@ module ActsAsFilterable
|
|
9
16
|
klazz.before_validation :apply_filters
|
10
17
|
end
|
11
18
|
|
12
|
-
private
|
13
|
-
|
14
|
-
module Language
|
15
|
-
|
16
|
-
def filter(&blk)
|
17
|
-
instance_eval blk
|
18
|
-
end
|
19
|
-
|
20
|
-
def digits(*args)
|
21
|
-
filtered_attributes[:digits] |= args unless args.empty?
|
22
|
-
end
|
23
|
-
|
24
|
-
def lowercase(*args)
|
25
|
-
filtered_attributes[:lowercase] |= args unless args.empty?
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
19
|
module ClassMethods
|
31
20
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end.freeze
|
21
|
+
def self.extended(klazz)
|
22
|
+
ActsAsFilterable::Filters.each_key do |key|
|
23
|
+
klazz.class_eval <<-MACROS, __FILE__, __LINE__ + 1
|
24
|
+
def self.filter_for_#{key}(*args)
|
25
|
+
filtered_attributes[:#{key}] |= args unless args.empty?
|
26
|
+
end
|
27
|
+
MACROS
|
28
|
+
end
|
41
29
|
end
|
42
30
|
|
43
31
|
def filtered_attributes
|
44
32
|
@filtered_attributes ||= Hash.new []
|
45
33
|
end
|
46
|
-
|
34
|
+
|
47
35
|
end
|
48
36
|
|
49
37
|
protected
|
50
|
-
|
38
|
+
|
51
39
|
def apply_filters
|
52
40
|
self.class.filtered_attributes.each do |key, value|
|
53
41
|
value.each do |attr|
|
54
|
-
|
42
|
+
apply_filter self, attr, ActsAsFilterable::Filters[key]
|
55
43
|
end
|
56
44
|
end
|
57
45
|
end
|
58
46
|
|
59
47
|
private
|
60
48
|
|
61
|
-
def apply_filter(
|
62
|
-
filter.
|
49
|
+
def apply_filter(record, attr, filter)
|
50
|
+
filter.call(record[attr]) if record[attr].is_a?(String)
|
63
51
|
end
|
64
52
|
|
65
53
|
end
|
data/lib/acts_as_filterable.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class ActsAsFilterableIntegrationTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
context "An ActiveRecord model using acts_as_filterable" do
|
6
6
|
setup do
|
7
7
|
@model = ContactDetail.new do |cd|
|
@@ -19,25 +19,13 @@ class ActsAsFilterableIntegrationTest < Test::Unit::TestCase
|
|
19
19
|
ContactDetail.respond_to?(:filtered_attributes).should be(true)
|
20
20
|
end
|
21
21
|
|
22
|
-
should "make it's filters available" do
|
23
|
-
ContactDetail.respond_to?(:filters).should be(true)
|
24
|
-
end
|
25
|
-
|
26
|
-
should "default filters that don't exist to an empty array" do
|
27
|
-
ContactDetail.filters[:test].empty?.should be(true)
|
28
|
-
end
|
29
|
-
|
30
|
-
should "contain some filters initially" do
|
31
|
-
ContactDetail.filters[:numeric].nil?.should_not be(true)
|
32
|
-
end
|
33
|
-
|
34
|
-
should "freeze the macro collection so it cannot be mutated" do
|
35
|
-
lambda { ContactDetail.filters.store(:test, /./) }.should raise_error
|
36
|
-
end
|
37
|
-
|
38
22
|
should "add a macro to filter non-numeric values from string fields" do
|
39
23
|
ContactDetail.respond_to?(:filter_for_digits).should be(true)
|
40
24
|
end
|
25
|
+
|
26
|
+
should "add a macro to filter values to lowercase from string fields" do
|
27
|
+
ContactDetail.respond_to?(:filter_for_lowercase).should be(true)
|
28
|
+
end
|
41
29
|
|
42
30
|
should "be savable with valid data" do
|
43
31
|
@model.save.should be(true)
|
@@ -74,12 +62,12 @@ class ActsAsFilterableIntegrationTest < Test::Unit::TestCase
|
|
74
62
|
end
|
75
63
|
end
|
76
64
|
|
77
|
-
context "with non-
|
65
|
+
context "with non-string attributes" do
|
78
66
|
setup do
|
79
67
|
ContactDetail.filter_for_digits :discount
|
80
68
|
end
|
81
69
|
|
82
|
-
should "not raise any errors due to a non-
|
70
|
+
should "not raise any errors due to a non-string attribute value" do
|
83
71
|
lambda { @model.valid? }.should_not raise_error
|
84
72
|
end
|
85
73
|
|
@@ -90,7 +78,7 @@ class ActsAsFilterableIntegrationTest < Test::Unit::TestCase
|
|
90
78
|
|
91
79
|
end
|
92
80
|
|
93
|
-
context "with an attribute value that contains no
|
81
|
+
context "with an attribute value that contains no values to be stripped" do
|
94
82
|
setup do
|
95
83
|
@model.phone_number = "2223334444"
|
96
84
|
@model.valid?
|
@@ -104,15 +92,11 @@ class ActsAsFilterableIntegrationTest < Test::Unit::TestCase
|
|
104
92
|
context "that has filtered attribute names that are identical to another filtered model" do
|
105
93
|
|
106
94
|
should "hold seperate collections of filtered_attributes" do
|
107
|
-
User.filtered_attributes.should_not
|
95
|
+
User.filtered_attributes.should_not === ContactDetail.filtered_attributes
|
108
96
|
end
|
109
97
|
|
110
|
-
should "not
|
111
|
-
ContactDetail.filtered_attributes
|
112
|
-
end
|
113
|
-
|
114
|
-
should "not add filtered attributes to models that they are not intended for" do
|
115
|
-
User.filtered_attributes.include?(:phone_number).should_not be(true)
|
98
|
+
should "not add attributes to other models errantly" do
|
99
|
+
ContactDetail.filtered_attributes[:digits].should_not include(:handle)
|
116
100
|
end
|
117
101
|
|
118
102
|
end
|
data/test/filter_test.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class FilterTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def assert_identity_after_filter(filter, value)
|
6
|
+
identity = value.object_id
|
7
|
+
filter.call(value)
|
8
|
+
identity.should == value.object_id
|
9
|
+
end
|
10
|
+
|
11
|
+
context "Filters" do
|
12
|
+
should "default filters that don't exist to an empty array" do
|
13
|
+
ActsAsFilterable::Filters[:test].empty?.should be(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "contain some filters initially" do
|
17
|
+
ActsAsFilterable::Filters[:numeric].nil?.should_not be(true)
|
18
|
+
ActsAsFilterable::Filters[:lowercase].nil?.should_not be(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
should "freeze the macro collection so it cannot be mutated" do
|
22
|
+
lambda { ActsAsFilterable::Filters.store(:test, /./) }.should raise_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "When applying the" do
|
27
|
+
|
28
|
+
context "digit filter, it" do
|
29
|
+
setup do
|
30
|
+
@filter = ActsAsFilterable::Filters[:digits]
|
31
|
+
end
|
32
|
+
|
33
|
+
should "strip any non-digit values from the string" do
|
34
|
+
value = "45tr.,2"
|
35
|
+
@filter.call(value)
|
36
|
+
value.should be("452")
|
37
|
+
end
|
38
|
+
|
39
|
+
should "not lose digit values" do
|
40
|
+
value = "432099132"
|
41
|
+
@filter.call(value)
|
42
|
+
value.should be("432099132")
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return a coercable numerica value" do
|
46
|
+
value = "4"
|
47
|
+
@filter.call(value)
|
48
|
+
value.to_i.should be(4)
|
49
|
+
end
|
50
|
+
|
51
|
+
should "not create extra string objects when replacing values" do
|
52
|
+
assert_identity_after_filter @filter, "54tr"
|
53
|
+
end
|
54
|
+
|
55
|
+
should "not create extra string objects when no values are to be replaced" do
|
56
|
+
assert_identity_after_filter @filter, "54"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
context "lowercase filter, it" do
|
62
|
+
setup do
|
63
|
+
@filter = ActsAsFilterable::Filters[:lowercase]
|
64
|
+
end
|
65
|
+
|
66
|
+
should "lowercase all alpha values" do
|
67
|
+
value = "FAIl STRING"
|
68
|
+
@filter.call(value)
|
69
|
+
value.should be("fail string")
|
70
|
+
end
|
71
|
+
|
72
|
+
should "not create extra string objects when replacing values" do
|
73
|
+
assert_identity_after_filter @filter, "TRANSLATE"
|
74
|
+
end
|
75
|
+
|
76
|
+
should "not create extra string objects when no values are to be replaced" do
|
77
|
+
assert_identity_after_filter @filter, "43"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "uppercase filter, it" do
|
82
|
+
setup do
|
83
|
+
@filter = ActsAsFilterable::Filters[:uppercase]
|
84
|
+
end
|
85
|
+
|
86
|
+
should "uppercase all alpha values" do
|
87
|
+
value = "lowercase string"
|
88
|
+
@filter.call(value)
|
89
|
+
value.should be("LOWERCASE STRING")
|
90
|
+
end
|
91
|
+
|
92
|
+
should "not create extra string objects when replacing values" do
|
93
|
+
assert_identity_after_filter @filter, "translate"
|
94
|
+
end
|
95
|
+
|
96
|
+
should "not create extra string objects when no values are to be replaced" do
|
97
|
+
assert_identity_after_filter @filter, "43"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "whitesapce filter, it" do
|
102
|
+
setup do
|
103
|
+
@filter = ActsAsFilterable::Filters[:whitespace]
|
104
|
+
end
|
105
|
+
|
106
|
+
should "replace all un-neccessary whitespace" do
|
107
|
+
value = "\t hai! this is neat\n\nok? \t"
|
108
|
+
@filter.call(value)
|
109
|
+
value.should be("hai! this is neat ok?")
|
110
|
+
end
|
111
|
+
|
112
|
+
should "trim the ends of the string" do
|
113
|
+
value = " this "
|
114
|
+
@filter.call(value)
|
115
|
+
value.should be("this")
|
116
|
+
end
|
117
|
+
|
118
|
+
should "not create extra string objects when replacing values" do
|
119
|
+
assert_identity_after_filter @filter, "TRANSLATE"
|
120
|
+
end
|
121
|
+
|
122
|
+
should "not create extra string objects when no values are to be replaced" do
|
123
|
+
assert_identity_after_filter @filter, "43"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -16,7 +16,7 @@ ActiveRecord::Schema.define do
|
|
16
16
|
t.float :discount
|
17
17
|
end
|
18
18
|
|
19
|
-
create_table :
|
19
|
+
create_table :users, :force => true do |t|
|
20
20
|
t.string :handle
|
21
21
|
t.string :phone_number
|
22
22
|
end
|
@@ -28,6 +28,7 @@ end
|
|
28
28
|
|
29
29
|
class User < ActiveRecord::Base
|
30
30
|
filter_for_digits :phone_number
|
31
|
+
filter_for_lowercase :handle
|
31
32
|
end
|
32
33
|
|
33
34
|
class Test::Unit::TestCase
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_filterable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Ares
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-29 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/acts_as_filterable/base.rb
|
75
75
|
- rails/init.rb
|
76
76
|
- test/acts_as_filterable_integration_test.rb
|
77
|
+
- test/filter_test.rb
|
77
78
|
- test/test_helper.rb
|
78
79
|
has_rdoc: true
|
79
80
|
homepage: http://github.com/rares/acts_as_filterable
|
@@ -99,10 +100,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
100
|
requirements: []
|
100
101
|
|
101
102
|
rubyforge_project:
|
102
|
-
rubygems_version: 1.3.
|
103
|
+
rubygems_version: 1.3.5
|
103
104
|
signing_key:
|
104
105
|
specification_version: 3
|
105
|
-
summary:
|
106
|
+
summary: Filter attributes and stuff.
|
106
107
|
test_files:
|
107
108
|
- test/acts_as_filterable_integration_test.rb
|
109
|
+
- test/filter_test.rb
|
108
110
|
- test/test_helper.rb
|