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 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 "rares-acts_as_filterable", :source => "http://gems.github.com"
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{TODO}
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
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 1
4
- :patch: 4
3
+ :minor: 2
4
+ :patch: 0
@@ -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.1.4"
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-09-08}
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.2}
35
- s.summary = %q{An ActiveRecord plugin that allows attribute-based filtering in order to normalize numeric data}
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 filter_for_digits(*args)
33
- filtered_attributes[:digits] |= args unless args.empty?
34
- end
35
-
36
- def filters
37
- @filters ||= returning(Hash.new([])) do |f|
38
- f[:digits] = Commands::Digits.new
39
- f[:lowercase] = Commands::Lowercase.new
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
- apply_filter self.class.filters[key], attr
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(filter, attr)
62
- filter.apply self, attr
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
@@ -1,7 +1,6 @@
1
1
  module ActsAsFilterable
2
2
  module ActiveRecordExt
3
3
  autoload :Base, "acts_as_filterable/base"
4
- autoload :Commands, "acts_as_filterable/commands"
5
4
  end
6
5
  end
7
6
 
@@ -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-character attributes" do
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-character attribute value" do
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 non-numeric values to be stripped" do
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 == ContactDetail.filtered_attributes
95
+ User.filtered_attributes.should_not === ContactDetail.filtered_attributes
108
96
  end
109
97
 
110
- should "not overwrite attributes for other models" do
111
- ContactDetail.filtered_attributes.include?(:fax_number).should_not be(nil)
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
@@ -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 :user do |t|
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.1.4
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-09-08 00:00:00 -04:00
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.4
103
+ rubygems_version: 1.3.5
103
104
  signing_key:
104
105
  specification_version: 3
105
- summary: An ActiveRecord plugin that allows attribute-based filtering in order to normalize numeric data
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