vacuum_cleaner 0.1.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/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ doc
2
+ pkg
3
+ .yardoc
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Lukas Westermann
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,6 @@
1
+ Vacuum Cleaner
2
+ ==============
3
+
4
+ A Ruby (and Rails) attribute normalization gem.
5
+
6
+ ** TODO **
data/Rakefile ADDED
@@ -0,0 +1,88 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'yard'
4
+ require File.join(File.dirname(__FILE__), 'lib', 'vacuum_cleaner')
5
+
6
+ desc 'Test the vacuum_cleaner plugin.'
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << 'lib'
9
+ t.libs << 'test'
10
+ t.pattern = 'test/**/*_test.rb'
11
+ t.verbose = true
12
+ end
13
+
14
+ desc 'Generate documentation for vacuum_cleaner. (requires yard)'
15
+ YARD::Rake::YardocTask.new(:doc) do |t|
16
+ t.files = ['lib/**/*.rb']
17
+ t.options = [
18
+ "--readme", "README.md",
19
+ "--title", "vacuum_cleaner (v#{VacuumCleaner::VERSION}) API Documentation"
20
+ ]
21
+ end
22
+
23
+ begin
24
+ require 'jeweler'
25
+ Jeweler::Tasks.new do |gemspec|
26
+ gemspec.name = "vacuum_cleaner"
27
+ gemspec.version = VacuumCleaner::VERSION
28
+ gemspec.summary = "Ruby (and Rails) attribute cleaning support, provides some nice default normalization strategies."
29
+ description = <<-DESC
30
+ ** Swoooosh ** - and all those leading and trailing whitespaces are gone, or ** Frooom ** - and the value
31
+ is normalized to always be prefixed by 'http://' and much more. Works with both plain old Ruby, and Rails (ActiveModel
32
+ and ActiveSupport).
33
+ DESC
34
+ gemspec.description = description.strip
35
+ gemspec.email = "lukas.westermann@gmail.com"
36
+ gemspec.homepage = "http://github.com/lwe/vacuum_cleaner"
37
+ gemspec.authors = ["Lukas Westermann"]
38
+ gemspec.licenses = %w{LICENSE}
39
+ gemspec.extra_rdoc_files = %w{README.md}
40
+
41
+ gemspec.add_development_dependency('shoulda', '>= 2.10.2')
42
+ gemspec.add_development_dependency('rr', '>= 0.10.5')
43
+ # gemspec.add_development_dependency('activesupport', '>= 2.3.5')
44
+ end
45
+ Jeweler::GemcutterTasks.new
46
+ rescue LoadError
47
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
48
+ end
49
+
50
+ desc 'Clean all generated files (.yardoc and doc/*)'
51
+ task :clean do |t|
52
+ FileUtils.rm_rf "doc"
53
+ FileUtils.rm_rf "pkg"
54
+ FileUtils.rm_rf ".yardoc"
55
+ end
56
+
57
+ namespace :metrics do
58
+ desc 'Report all metrics, i.e. stats and code coverage.'
59
+ task :all => [:stats, :coverage]
60
+
61
+ desc 'Report code statistics for library and tests to shell.'
62
+ task :stats do |t|
63
+ require 'code_statistics'
64
+ dirs = {
65
+ 'Libraries' => 'lib',
66
+ 'Unit tests' => 'test/unit'
67
+ }.map { |name,dir| [name, File.join(File.dirname(__FILE__), dir)] }
68
+ CodeStatistics.new(*dirs).to_s
69
+ end
70
+
71
+ desc 'Report code coverage to HTML (doc/coverage) and shell (requires rcov).'
72
+ task :coverage do |t|
73
+ rm_f "doc/coverage"
74
+ mkdir_p "doc/coverage"
75
+ rcov = %(rcov -Ilib:test --exclude '\/gems\/' -o doc/coverage -T test/unit/vacuum_cleaner/*_test.rb -T test/unit/vacuum_cleaner/*/*_test.rb)
76
+ system rcov
77
+ end
78
+
79
+ desc 'Report the fishy smell of bad code (requires reek)'
80
+ task :smelly do |t|
81
+ puts
82
+ puts "* * * NOTE: reek currently reports several false positives,"
83
+ puts " eventhough it's probably good to check once in a while!"
84
+ puts
85
+ reek = %(reek -s lib)
86
+ system reek
87
+ end
88
+ end
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'vacuum_cleaner'
2
+
3
+ ActiveRecord::Base.class_eval { include VacuumCleaner::Normalizations } # all versions of rails
4
+ ActiveModel::Base.class_eval { include VacuumCleaner::Normalizations } if defined?(ActiveModel::Base) # Rails 3+
@@ -0,0 +1,6 @@
1
+ module VacuumCleaner
2
+ VERSION = "0.1.0".freeze
3
+
4
+ autoload :Normalizer, 'vacuum_cleaner/normalizer'
5
+ autoload :Normalizations, 'vacuum_cleaner/normalizations'
6
+ end
@@ -0,0 +1,69 @@
1
+ module VacuumCleaner
2
+ # Suffix added to existing setter methods
3
+ WITHOUT_NORMALIZATION_SUFFIX = "_without_normalization"
4
+
5
+ module Normalizations
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def normalizes(*attributes, &block)
13
+ metaklass = class << self; self; end
14
+
15
+ normalizations = attributes.last.is_a?(Hash) ? attributes.pop : {}
16
+ raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
17
+
18
+ normalizers = []
19
+ normalizers << Normalizer.new unless normalizations.delete(:default) === false
20
+
21
+ normalizations.each do |key, options|
22
+ begin
23
+ normalizers << const_get("#{VacuumCleaner.camelize_value(key)}Normalizer").new(options === true ? {} : options)
24
+ rescue NameError
25
+ raise ArgumentError, "Unknown normalizer: '#{key}'"
26
+ end
27
+ end
28
+
29
+ attributes.each do |attribute|
30
+ attribute = attribute.to_sym
31
+ send(:define_method, :"normalize_#{attribute}") do |value|
32
+ value = normalizers.inject(value) { |v,n| n.normalize(self, attribute, v) }
33
+ block_given? ? (block.arity == 1 ? yield(value) : yield(self, attribute, value)) : value
34
+ end
35
+ original_setter = "#{attribute}#{VacuumCleaner::WITHOUT_NORMALIZATION_SUFFIX}=".to_sym
36
+ send(:alias_method, original_setter, "#{attribute}=") if instance_methods.include?("#{attribute}=")
37
+
38
+ rb_src = <<-RUBY
39
+ def #{attribute}=(value) # 1. def name=(value)
40
+ value = send(:'normalize_#{attribute}', value) # 2. value = send(:'normalize_name', value)
41
+ return send(#{original_setter.inspect}, value) if respond_to?(#{original_setter.inspect}) # 3. return send(:'name_wo...=', value) if respond_to?(:'name_wo...=')
42
+ return send(:write_attribute, #{attribute.inspect}, value) if respond_to?(:write_attribute) # 4. return send(:write_attribute, :name, value) if respond_to?(:write_attribute)
43
+ @#{attribute} = value # 5. @name = value
44
+ end # 6. end
45
+ RUBY
46
+
47
+ module_eval rb_src, __FILE__, __LINE__
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ # Okay, because this library currently does not depend on
54
+ # <tt>ActiveSupport</tt> or anything similar an "independent" camelizing process is
55
+ # required. So it works pretty easy.
56
+ #
57
+ # If <tt>value.to_s</tt> responds to <tt>:camelize</tt>, then call it else use implementation
58
+ # taken from http://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L25
59
+ def camelize_value(value)
60
+ value = value.to_s
61
+ value.respond_to?(:camelize) ? value.camelize : value.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
62
+ end
63
+ module_function :camelize_value
64
+ end
65
+
66
+ # load standard normalizations
67
+ Dir[File.dirname(__FILE__) + "/normalizations/*.rb"].sort.each do |path|
68
+ require "vacuum_cleaner/normalizations/#{File.basename(path)}"
69
+ end
@@ -0,0 +1,48 @@
1
+ module VacuumCleaner
2
+ module Normalizations
3
+
4
+ # Generic method based normalizer which just calls supplied method
5
+ # on value (unless nil).
6
+ #
7
+ # normalizes :name, :method => :titelize
8
+ #
9
+ # Custom instances accept a <tt>:method</tt> option.
10
+ #
11
+ # MethodNormalizer.new(:method => :titelize)
12
+ #
13
+ # Subclasses of the +MethodNormalizer+ can take advantage of it's
14
+ # +normalize_if_respond_to+ method, to easily create custom
15
+ # normalizers based on methods availble on the result value.
16
+ class MethodNormalizer < Normalizer
17
+ # Ensure access to default normalization method
18
+ alias_method :default_normalize_value, :normalize_value
19
+
20
+ # Helper method to "bake" a method normalizer from a method, enabling us to do stuff like.
21
+ #
22
+ # TitelizeNormalizer = MethodNormalizer.build(:titleize)
23
+ #
24
+ def self.build(sym)
25
+ module_eval "Class.new(MethodNormalizer) do; def initialize(*args); super({ :method => #{sym.inspect}}) end; end", __FILE__, __LINE__
26
+ end
27
+
28
+ # Accept either a hash or symbol name.
29
+ def initialize(args = {})
30
+ args = { :method => args } unless args.is_a?(Hash)
31
+ super(args)
32
+ end
33
+
34
+ # Normalize value by calling the default normalizer (strip + nil if empty)
35
+ # and then if not <tt>nil</tt> call the method defined.
36
+ def normalize_value(value)
37
+ sym = options[:method]
38
+ value.respond_to?(sym) ? value.send(sym) : value
39
+ end
40
+ end
41
+
42
+ # Downcase value unless nil or empty.
43
+ DowncaseNormalizer = MethodNormalizer.build(:downcase)
44
+
45
+ # Upcases value unless nil or empty.
46
+ UpcaseNormalizer = MethodNormalizer.build(:upcase)
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module VacuumCleaner
2
+ module Normalizations
3
+ class UrlNormalizer < Normalizer
4
+ def initialize(options = {})
5
+ options = { :scheme => "http://", :unless => %r{\Ahttps?://}i } if options.nil? || options.empty?
6
+ options = { :scheme => options, :unless => %r{\A#{options}}i } unless options.is_a?(Hash)
7
+ super(options)
8
+ end
9
+
10
+ def normalize_value(value)
11
+ value =~ options[:unless] ? value : "#{options[:scheme]}#{value}" unless value.nil?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ module VacuumCleaner #:nodoc:
2
+
3
+ # A small base class for implementing custom value normalizers.
4
+ # Might seem like a slight overkill, yet makes the library pretty
5
+ # reusable and all. Based on Rails 3 validator stuff.
6
+ #
7
+ #
8
+ # class Person
9
+ # include VacuumCleaner::Normalizations
10
+ # normalizes :name, :titleize => true
11
+ # end
12
+ #
13
+ # class TitleizeNormalizer < VacuumCleaner::Normalizer
14
+ # def normalize_value(value)
15
+ # value.titelize unless value.blank?
16
+ # end
17
+ # end
18
+ #
19
+ # Any class that inherits from +VacuumCleaner::Normalizer+ must implement
20
+ # a method called <tt>normalize_value</tt> which accepts the <tt>value</tt> to normalize. Furthermore
21
+ # the value returned by <tt>normalize</tt> is used as the new value for
22
+ # the attribute.
23
+ #
24
+ # To reuse the behaviour as defined by the default normalizer (strip & empty),
25
+ # just use <tt>super</tt>.
26
+ #
27
+ # class TitleizeNormalizer < VacuumCleaner::Normalizer
28
+ # def normalize_value(value)
29
+ # super(value).try(:titelize)
30
+ # end
31
+ # end
32
+ #
33
+ # If access to the record or attribute being normalized is required the method
34
+ # +normalize+ can be overriden instead.
35
+ #
36
+ # class FancyNormalizer < VacuumCleaner::Normalizer
37
+ # def normalize(object, attribute, value)
38
+ # ...
39
+ # end
40
+ # end
41
+ #
42
+ # This can be used together with the +normalizes+ method (see
43
+ # VacuumCleaner::Normalizers.normalizes for more on this).
44
+ class Normalizer
45
+ attr_reader :options
46
+
47
+ # Accepts an array of options, which will be made available through the +options+ reader.
48
+ def initialize(options = {})
49
+ @options = options
50
+ end
51
+
52
+ # Only override this method if access to the <tt>object</tt> or <tt>attribute</tt> name
53
+ # is required, else override +normalize_value+, makes life much simpler :)
54
+ #
55
+ # Default behaviour just calls <tt>normalize_value(value)</tt>.
56
+ def normalize(object, attribute, value); normalize_value(value) end
57
+
58
+ # Override this method in subclasses to specifiy custom normalization steps and magic.
59
+ #
60
+ # The standard implementation strips the value of trailing/leading whitespace and then
61
+ # either returns that value or +nil+ if it's <tt>empty?</tt>.
62
+ def normalize_value(value)
63
+ value = value.strip if value.respond_to?(:strip)
64
+ value.nil? || (value.respond_to?(:empty?) && value.empty?) ? nil : value
65
+ end
66
+ end
67
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'vacuum_cleaner'
2
+
3
+ ActiveRecord::Base.class_eval { include VacuumCleaner::Normalizations } # all versions of rails
4
+ ActiveModel::Base.class_eval { include VacuumCleaner::Normalizations } if defined?(ActiveModel::Base) # Rails 3+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'rr'
5
+
6
+ # require 'normalo'
7
+
8
+ Test::Unit::TestCase.send(:include, RR::Adapters::TestUnit)
9
+
10
+ # Dir[File.dirname(__FILE__) + "/fixtures/*.rb"].each { |fixture| require fixture }
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+ require 'vacuum_cleaner/normalizer'
3
+ require 'vacuum_cleaner/normalizations/method'
4
+
5
+ class VacuumCleaner::Normalizations::MethodTest < Test::Unit::TestCase
6
+ include VacuumCleaner::Normalizations
7
+
8
+ context "MethodNormalizer" do
9
+ should "accept method name as initialization argument" do
10
+ downcaser = MethodNormalizer.new(:downcase)
11
+ assert_equal "elliot\n", downcaser.normalize_value("Elliot\n")
12
+ assert_equal " \t", downcaser.normalize_value(" \t")
13
+ end
14
+
15
+ should "accept hash with :method key as initializer" do
16
+ upcaser = MethodNormalizer.new(:method => :upcase)
17
+ assert_equal "ELLIOT\n", upcaser.normalize_value("Elliot\n")
18
+ assert_equal " \t", upcaser.normalize_value(" \t")
19
+ end
20
+ end
21
+
22
+ context "DowncaseNormalizer#normalize_value" do
23
+ should "downcase input" do
24
+ assert_equal "elliot", DowncaseNormalizer.new.normalize_value("Elliot")
25
+ end
26
+ end
27
+
28
+ context "UpcaseNormalizer#normalize_value" do
29
+ should "upcase input" do
30
+ assert_equal "J.D.", UpcaseNormalizer.new.normalize_value("j.d.")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+ require 'vacuum_cleaner/normalizer'
3
+ require 'vacuum_cleaner/normalizations/url'
4
+
5
+ class VacuumCleaner::Normalizations::UrlTest < Test::Unit::TestCase
6
+ include VacuumCleaner::Normalizations
7
+
8
+ #
9
+ # normalizes :homepage, :url => true
10
+ # normalizes :ftp, :url => "ftp://"
11
+ # normalizes :uri, :url => { :scheme => "http://", :unless => %r{\A(https?://|ftp://|jabber:)} }
12
+ #
13
+ context "UrlNormalizer#normalize_value" do
14
+ should "ignore <nil>" do
15
+ assert_nil UrlNormalizer.new.normalize_value(nil)
16
+ end
17
+
18
+ should "prefix string with 'http://' if string does not begin with it" do
19
+ assert_equal "http://google.com", UrlNormalizer.new.normalize_value("google.com")
20
+ end
21
+
22
+ should "not prefix string with 'http://' if string already begins with http or https" do
23
+ assert_equal "http://google.com/", UrlNormalizer.new.normalize_value("http://google.com/")
24
+ assert_equal "https://docs.google.com/", UrlNormalizer.new.normalize_value("https://docs.google.com/")
25
+ end
26
+
27
+ should "allow to specify custom scheme, like ftp://" do
28
+ assert_equal "ftp://ftp.sacred-heart.com", UrlNormalizer.new("ftp://").normalize_value("ftp.sacred-heart.com")
29
+ assert_equal "ftp://ftp.sacred-heart.com", UrlNormalizer.new("ftp://").normalize_value("ftp://ftp.sacred-heart.com")
30
+ end
31
+
32
+ should "allow to specify :scheme and custom regex to exclude/allow certain protocols" do
33
+ n = UrlNormalizer.new(:scheme => "http://", :unless => %r{\A(https?://|ftp://|jabber:)})
34
+ assert_equal "http://google.com", n.normalize_value("google.com")
35
+ assert_equal "jabber:jd@sh.com", n.normalize_value("jabber:jd@sh.com")
36
+ assert_equal "https://docs.google.com", n.normalize_value("https://docs.google.com")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,192 @@
1
+ require 'test_helper'
2
+
3
+ require 'vacuum_cleaner/normalizer'
4
+ require 'vacuum_cleaner/normalizations'
5
+
6
+ class PrefixDoctorNormalizer < VacuumCleaner::Normalizer
7
+ def normalize_value(value)
8
+ "Dr. #{value}"
9
+ end
10
+ end
11
+
12
+ class Person
13
+ include VacuumCleaner::Normalizations
14
+
15
+ attr_accessor :last_name, :first_name
16
+
17
+ normalizes :last_name
18
+ normalizes :first_name
19
+ end
20
+
21
+ class Doctor
22
+ include VacuumCleaner::Normalizations
23
+ attr_accessor :name
24
+
25
+ class GirlifyNormalizer < VacuumCleaner::Normalizer
26
+ def normalize_value(value)
27
+ value == "J.D." ? "Maria" : value
28
+ end
29
+ end
30
+
31
+ normalizes :name, :girlify => true
32
+ end
33
+
34
+ class VacuumCleaner::NormalizationsTest < Test::Unit::TestCase
35
+ context "VacuumCleaner::Normalizations" do
36
+ context "ClassMethods#normalizes" do
37
+ should "throw ArgumentError if no attributes are passed in" do
38
+ assert_raise ArgumentError do
39
+ klass = Class.new do
40
+ include VacuumCleaner::Normalizations
41
+ normalizes
42
+ end
43
+ end
44
+ end
45
+
46
+ should "take a symbol as argument" do
47
+ assert_respond_to Class.new { include VacuumCleaner::Normalizations; normalizes(:name) }, :normalizes
48
+ end
49
+
50
+ should "take multiple symbols as argument" do
51
+ klass = Class.new { include VacuumCleaner::Normalizations; normalizes(:name, :first_name) }
52
+ assert_respond_to klass, :normalizes
53
+ #assert_respond_to klass, :normalize_name
54
+ #assert_respond_to klass, :normalize_first_name
55
+ end
56
+
57
+ should "create a setter for supplied attribute" do
58
+ obj = Class.new { include VacuumCleaner::Normalizations; normalizes(:name) }.new
59
+ assert_respond_to obj, :name=
60
+ end
61
+
62
+ should "set the instance variable using the setter" do
63
+ obj = Class.new { include VacuumCleaner::Normalizations; normalizes(:name) }.new
64
+ obj.name = "J.D."
65
+ assert_equal "J.D.", obj.instance_variable_get(:@name)
66
+ end
67
+
68
+ should "alias method to <attr>_without_normalization= if <attr>= already defined" do
69
+ klass = Class.new do
70
+ include VacuumCleaner::Normalizations
71
+ def name=(name); @foo = name end
72
+ normalizes :name
73
+ end
74
+ obj = klass.new
75
+ obj.name = "Elliot Reid"
76
+ assert_respond_to obj, :name_without_normalization=
77
+ assert_equal "Elliot Reid", obj.instance_variable_get(:@foo)
78
+ assert_nil obj.instance_variable_get(:@name)
79
+ end
80
+
81
+ should "convert any blank input, like empty string, nil etc. to => <nil>" do
82
+ obj = Person.new
83
+ obj.first_name = " "
84
+ obj.last_name = ''
85
+ assert_nil obj.first_name
86
+ assert_nil obj.last_name
87
+ end
88
+
89
+ should "strip leading and trailing white-space" do
90
+ obj = Person.new
91
+ obj.first_name = "\nElliot\t "
92
+ obj.last_name = nil
93
+ assert_nil obj.last_name
94
+ assert_equal "Elliot", obj.first_name
95
+ end
96
+
97
+ should "accept a block which overrides the default to_nil_if_empty strategy" do
98
+ klass = Class.new do
99
+ include VacuumCleaner::Normalizations
100
+ attr_accessor :name
101
+ normalizes :name do |value|
102
+ value ? value.upcase : value
103
+ end
104
+ end
105
+ obj = klass.new
106
+ obj.name = "Turk"
107
+ assert_equal "TURK", obj.name
108
+ end
109
+
110
+ should "accept custom options hash to define other normalizers to run" do
111
+ klass = Class.new do
112
+ include VacuumCleaner::Normalizations
113
+ attr_accessor :email
114
+ normalizes :email, :downcase => true
115
+ end
116
+ obj = klass.new
117
+ obj.email = "\nJ.D.Dorian@Sacred-Heart.com "
118
+ assert_equal "j.d.dorian@sacred-heart.com", obj.email
119
+ end
120
+
121
+ should "raise ArgumentError if invalid/unknown normalizer is called" do
122
+ assert_raise ArgumentError do
123
+ Class.new do
124
+ include VacuumCleaner::Normalizations
125
+ normalizes :foo, :invalid_unknown_normalizer => true
126
+ end
127
+ end
128
+ end
129
+
130
+ should "ignore default split/empty? normalizer if :default => false" do
131
+ klass = Class.new do
132
+ include VacuumCleaner::Normalizations
133
+ attr_accessor :name
134
+ normalizes :name, :default => false, :upcase => true
135
+ end
136
+ obj = klass.new
137
+ obj.name = "Dr. Dorian\n\t"
138
+ assert_equal "DR. DORIAN\n\t", obj.name
139
+ end
140
+
141
+ should "be able to use normalizers from the global namespace" do
142
+ klass = Class.new do
143
+ include VacuumCleaner::Normalizations
144
+ attr_accessor :name
145
+ normalizes :name, :prefix_doctor => true
146
+ end
147
+ obj = klass.new
148
+ obj.name = "Elliot Reid"
149
+ assert_equal "Dr. Elliot Reid", obj.name
150
+ end
151
+
152
+ should "be able to use normalizers from within the class itself" do
153
+ obj = Doctor.new
154
+ obj.name = "Elliot Reid"
155
+ assert_equal "Elliot Reid", obj.name
156
+ obj = Doctor.new
157
+ obj.name = "J.D."
158
+ assert_equal "Maria", obj.name
159
+ end
160
+
161
+ should "be able to combine normalizers and custom blocks" do
162
+ klass = Class.new do
163
+ include VacuumCleaner::Normalizations
164
+ attr_accessor :name, :first_name
165
+ normalizes(:name, :first_name, :downcase => true) do |value|
166
+ value.nil? ? value : "#{value.to_s[0,1].upcase}#{value.to_s[1..-1]}"
167
+ end
168
+ end
169
+
170
+ obj = klass.new
171
+ obj.name = "REID"
172
+ obj.first_name = "ELLIOT"
173
+ assert_equal "Reid", obj.name
174
+ assert_equal "Elliot", obj.first_name
175
+ end
176
+
177
+ should "provide block with all values if asking for them!" do
178
+ klass = Class.new do
179
+ include VacuumCleaner::Normalizations
180
+ attr_accessor :name
181
+ normalizes(:name) do |object, attribute, value|
182
+ [object.object_id, attribute, value]
183
+ end
184
+ end
185
+
186
+ obj = klass.new
187
+ obj.name = "Carla"
188
+ assert_equal [obj.object_id, :name, "Carla"], obj.name
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+ require 'vacuum_cleaner/normalizer'
3
+
4
+ class VacuumCleaner::NormalizerTest < Test::Unit::TestCase
5
+ context "VacuumCleaner::Normalizer" do
6
+ should "take an optional hash as argument during #initialize and expose that hash when calling #options" do
7
+ expected = { :doctor => "Dr. Dorian", :nurse => "Carla" }
8
+ normalizer = VacuumCleaner::Normalizer.new({ :doctor => "Dr. Dorian", :nurse => "Carla" })
9
+ assert_equal "Dr. Dorian", normalizer.options[:doctor]
10
+ assert_equal expected, normalizer.options
11
+ end
12
+
13
+ context "#normalize_value" do
14
+ should "leave <nil>" do
15
+ assert_nil VacuumCleaner::Normalizer.new.normalize_value(nil)
16
+ end
17
+
18
+ should "convert empty string to <nil>" do
19
+ assert_nil VacuumCleaner::Normalizer.new.normalize_value('')
20
+ end
21
+
22
+ should "convert string with only space characters to <nil>" do
23
+ assert_nil VacuumCleaner::Normalizer.new.normalize_value(" ")
24
+ assert_nil VacuumCleaner::Normalizer.new.normalize_value(" \n\t ")
25
+ end
26
+
27
+ should "strip leading and trailing whitespace" do
28
+ assert_equal "Dr. Reid", VacuumCleaner::Normalizer.new.normalize_value(" \nDr. Reid\t ")
29
+ assert_equal "Dr. Dorian", VacuumCleaner::Normalizer.new.normalize_value("Dr. Dorian\t \r")
30
+ end
31
+ end
32
+
33
+ context "#normalize" do
34
+ should "return always the same as #normalize_value and ignore object and attribute parameters" do
35
+ normalizer = VacuumCleaner::Normalizer.new
36
+ object = Object.new
37
+ attribute = :name
38
+
39
+ [["Dr. Reid", "\t Dr. Reid"], ["Dr. Dorian", "Dr. Dorian\n "], [nil, nil], [nil, "\n "], [nil, ""]].each do |tests|
40
+ expected, value = *tests
41
+ assert_equal expected, normalizer.normalize_value(value)
42
+ assert_equal expected, normalizer.normalize(object, attribute, value)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{vacuum_cleaner}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Lukas Westermann"]
12
+ s.date = %q{2010-02-24}
13
+ s.description = %q{** Swoooosh ** - and all those leading and trailing whitespaces are gone, or ** Frooom ** - and the value
14
+ is normalized to always be prefixed by 'http://' and much more. Works with both plain old Ruby, and Rails (ActiveModel
15
+ and ActiveSupport).}
16
+ s.email = %q{lukas.westermann@gmail.com}
17
+ s.extra_rdoc_files = [
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "init.rb",
26
+ "lib/vacuum_cleaner.rb",
27
+ "lib/vacuum_cleaner/normalizations.rb",
28
+ "lib/vacuum_cleaner/normalizations/method.rb",
29
+ "lib/vacuum_cleaner/normalizations/url.rb",
30
+ "lib/vacuum_cleaner/normalizer.rb",
31
+ "rails/init.rb",
32
+ "test/test_helper.rb",
33
+ "test/unit/vacuum_cleaner/normalizations/method_test.rb",
34
+ "test/unit/vacuum_cleaner/normalizations/url_test.rb",
35
+ "test/unit/vacuum_cleaner/normalizations_test.rb",
36
+ "test/unit/vacuum_cleaner/normalizer_test.rb",
37
+ "vacuum_cleaner.gemspec"
38
+ ]
39
+ s.homepage = %q{http://github.com/lwe/vacuum_cleaner}
40
+ s.licenses = ["LICENSE"]
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.6}
44
+ s.summary = %q{Ruby (and Rails) attribute cleaning support, provides some nice default normalization strategies.}
45
+ s.test_files = [
46
+ "test/test_helper.rb",
47
+ "test/unit/vacuum_cleaner/normalizations/method_test.rb",
48
+ "test/unit/vacuum_cleaner/normalizations/url_test.rb",
49
+ "test/unit/vacuum_cleaner/normalizations_test.rb",
50
+ "test/unit/vacuum_cleaner/normalizer_test.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ s.add_development_dependency(%q<shoulda>, [">= 2.10.2"])
59
+ s.add_development_dependency(%q<rr>, [">= 0.10.5"])
60
+ else
61
+ s.add_dependency(%q<shoulda>, [">= 2.10.2"])
62
+ s.add_dependency(%q<rr>, [">= 0.10.5"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<shoulda>, [">= 2.10.2"])
66
+ s.add_dependency(%q<rr>, [">= 0.10.5"])
67
+ end
68
+ end
69
+
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vacuum_cleaner
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Lukas Westermann
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-02-24 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 10
30
+ - 2
31
+ version: 2.10.2
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rr
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 10
44
+ - 5
45
+ version: 0.10.5
46
+ type: :development
47
+ version_requirements: *id002
48
+ description: |-
49
+ ** Swoooosh ** - and all those leading and trailing whitespaces are gone, or ** Frooom ** - and the value
50
+ is normalized to always be prefixed by 'http://' and much more. Works with both plain old Ruby, and Rails (ActiveModel
51
+ and ActiveSupport).
52
+ email: lukas.westermann@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - README.md
59
+ files:
60
+ - .gitignore
61
+ - LICENSE
62
+ - README.md
63
+ - Rakefile
64
+ - init.rb
65
+ - lib/vacuum_cleaner.rb
66
+ - lib/vacuum_cleaner/normalizations.rb
67
+ - lib/vacuum_cleaner/normalizations/method.rb
68
+ - lib/vacuum_cleaner/normalizations/url.rb
69
+ - lib/vacuum_cleaner/normalizer.rb
70
+ - rails/init.rb
71
+ - test/test_helper.rb
72
+ - test/unit/vacuum_cleaner/normalizations/method_test.rb
73
+ - test/unit/vacuum_cleaner/normalizations/url_test.rb
74
+ - test/unit/vacuum_cleaner/normalizations_test.rb
75
+ - test/unit/vacuum_cleaner/normalizer_test.rb
76
+ - vacuum_cleaner.gemspec
77
+ has_rdoc: true
78
+ homepage: http://github.com/lwe/vacuum_cleaner
79
+ licenses:
80
+ - LICENSE
81
+ post_install_message:
82
+ rdoc_options:
83
+ - --charset=UTF-8
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project:
103
+ rubygems_version: 1.3.6
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: Ruby (and Rails) attribute cleaning support, provides some nice default normalization strategies.
107
+ test_files:
108
+ - test/test_helper.rb
109
+ - test/unit/vacuum_cleaner/normalizations/method_test.rb
110
+ - test/unit/vacuum_cleaner/normalizations/url_test.rb
111
+ - test/unit/vacuum_cleaner/normalizations_test.rb
112
+ - test/unit/vacuum_cleaner/normalizer_test.rb