vacuum_cleaner 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -3,22 +3,13 @@ require 'rake/testtask'
3
3
 
4
4
  require File.join(File.dirname(__FILE__), 'lib', 'vacuum_cleaner')
5
5
 
6
- task :default => :test
7
-
8
- desc 'Test the vacuum_cleaner plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.libs << 'test'
12
- t.pattern = 'test/**/*_test.rb'
13
- t.verbose = true
14
- end
15
-
16
6
  begin
17
7
  require 'yard'
18
8
  desc 'Generate documentation for vacuum_cleaner. (requires yard)'
19
9
  YARD::Rake::YardocTask.new(:doc) do |t|
20
10
  t.files = ['lib/**/*.rb']
21
11
  t.options = [
12
+ "--no-private",
22
13
  "--readme", "README.md",
23
14
  "--title", "vacuum_cleaner (v#{VacuumCleaner::VERSION}) API Documentation"
24
15
  ]
@@ -42,7 +33,6 @@ begin
42
33
  gemspec.extra_rdoc_files = %w{README.md}
43
34
 
44
35
  gemspec.add_development_dependency('shoulda', '>= 2.10.2')
45
- gemspec.add_development_dependency('rr', '>= 0.10.5')
46
36
  gemspec.add_development_dependency('activesupport', '>= 2.3.5')
47
37
 
48
38
  gemspec.files.reject! { |file| file =~ /\.gemspec$/ } # kinda redundant
@@ -59,6 +49,24 @@ task :clean do |t|
59
49
  FileUtils.rm_rf ".yardoc"
60
50
  end
61
51
 
52
+ namespace :test do
53
+ desc 'Test the vacuum_cleaner plugin.'
54
+ Rake::TestTask.new(:unit) do |t|
55
+ t.libs << 'test'
56
+ t.pattern = 'test/unit/**/*_test.rb'
57
+ t.verbose = true
58
+ end
59
+
60
+ desc 'Run integration tests for the vacuum_cleaner plugin.'
61
+ Rake::TestTask.new(:integration) do |t|
62
+ t.libs << 'test'
63
+ t.pattern = 'test/integration/**/*_test.rb'
64
+ t.verbose = true
65
+ end
66
+
67
+ task :all => [:'test:unit', :'test:integration']
68
+ end
69
+
62
70
  namespace :metrics do
63
71
  desc 'Report all metrics, i.e. stats and code coverage.'
64
72
  task :all => [:stats, :coverage]
data/init.rb CHANGED
@@ -1 +1 @@
1
- require File.dirname(__FILE__) + "rails/init"
1
+ require File.join(File.dirname(__FILE__), 'rails', 'init')
@@ -1,7 +1,11 @@
1
- # Fancy value normalization utility for ruby (and rails).
1
+ # Fancy value normalization utility for ruby (and rails),
2
+ # see {VacuumCleaner::Normalizations} for more information about usage.
3
+ #
4
+ # @see VacuumCleaner::Normalizations
5
+ # @see VacuumCleaner::Normalizer
2
6
  module VacuumCleaner
3
- # +VacuumCleaner+ version string, current version is 0.1.0.
4
- VERSION = "0.5.0".freeze
7
+ # +VacuumCleaner+ version
8
+ VERSION = "1.0.0".freeze
5
9
 
6
10
  autoload :Normalizer, 'vacuum_cleaner/normalizer'
7
11
  autoload :Normalizations, 'vacuum_cleaner/normalizations'
@@ -1,7 +1,11 @@
1
1
  module VacuumCleaner
2
+
3
+ # @private
2
4
  # Suffix added to existing setter methods
3
5
  WITHOUT_NORMALIZATION_SUFFIX = "_without_normalization"
4
6
 
7
+ # Base module required to be included in
8
+ #
5
9
  module Normalizations
6
10
 
7
11
  def self.included(base)
@@ -9,6 +13,27 @@ module VacuumCleaner
9
13
  end
10
14
 
11
15
  module ClassMethods
16
+
17
+ # Enables normalization chain for supplied attributes.
18
+ #
19
+ # @example Basic usage for plain old ruby objects.
20
+ # class Doctor
21
+ # include VacuumCleaner::Normalizations
22
+ # attr_accessor :name
23
+ # normalizes :name
24
+ # end
25
+ #
26
+ #
27
+ # @param [Strings, Symbols] attributes list of attribute names to normalize, at least one attribute is required
28
+ # @param [Hash] options optional list of normalizers to use, like +:downcase => true+. To not run the default
29
+ # normalizer ({VacuumCleaner::Normalizer#normalize_value}) set +:default => false+
30
+ #
31
+ # @yield [value] optional block to define some one-time custom normalization logic
32
+ # @yieldparam value can be +nil+, otherwise value as passed through the default normalizer
33
+ # @yieldreturn should return value as normalized by the block
34
+ #
35
+ # @yield [instance, attribute, value] optional (extended) block with all arguments, like the +object+ and
36
+ # current +attribute+ name. Everything else behaves the same es the single-value +yield+
12
37
  def normalizes(*attributes, &block)
13
38
  metaklass = class << self; self; end
14
39
 
@@ -38,8 +63,8 @@ module VacuumCleaner
38
63
  rb_src = <<-RUBY
39
64
  def #{attribute}=(value) # 1. def name=(value)
40
65
  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)
66
+ return send(#{original_setter.inspect}, value) if respond_to?(#{original_setter.inspect}) # 3. return send(:'name_wi...=', value) if respond_to?(:'name_wi...=')
67
+ return self[#{attribute.inspect}] = value if respond_to?(:[]=) # 4. return self[:name] = value if respond_to?(:write_attribute)
43
68
  @#{attribute} = value # 5. @name = value
44
69
  end # 6. end
45
70
  RUBY
@@ -50,6 +75,7 @@ module VacuumCleaner
50
75
  end
51
76
  end
52
77
 
78
+ # @private
53
79
  # Okay, because this library currently does not depend on
54
80
  # <tt>ActiveSupport</tt> or anything similar an "independent" camelizing process is
55
81
  # required.
@@ -13,10 +13,7 @@ module VacuumCleaner
13
13
  # Subclasses of the +MethodNormalizer+ can take advantage of it's
14
14
  # +normalize_if_respond_to+ method, to easily create custom
15
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
-
16
+ class MethodNormalizer < Normalizer
20
17
  # Helper method to "bake" a method normalizer from a method, enabling us to do stuff like.
21
18
  #
22
19
  # TitelizeNormalizer = MethodNormalizer.build(:titleize)
@@ -31,11 +28,11 @@ module VacuumCleaner
31
28
  super(args)
32
29
  end
33
30
 
34
- # Normalize value by calling the default normalizer (strip + nil if empty)
35
- # and then if not <tt>nil</tt> call the method defined.
31
+ # Normalize value by trying to call the method at hand, if
32
+ # +value+ does not respond to the defined method, returns +nil+.
36
33
  def normalize_value(value)
37
34
  sym = options[:method]
38
- value.respond_to?(sym) ? value.send(sym) : value
35
+ value.respond_to?(sym) ? value.send(sym) : nil
39
36
  end
40
37
  end
41
38
 
@@ -1,17 +1,38 @@
1
1
  module VacuumCleaner
2
2
  module Normalizations
3
3
 
4
- #
4
+ # Normalizer which is used to prefix strings with a scheme, if missing.
5
+ # This is useful to ensure, that an input field always has e.g. the
6
+ # "http://" scheme added. Please note, that this normalizer does not
7
+ # validate a URL in any way.
5
8
  #
9
+ # normalizes :homepage, :url => true
6
10
  #
11
+ # Accepts a string as input, so to normalize for instance FTP URLs.
12
+ #
13
+ # normalizes :download_url, :url => "ftp://"
14
+ #
15
+ # To make further customizations, the constructor accepts a hash.
16
+ #
17
+ # normalizes, :contact_url, :url => { :scheme => "http://",
18
+ # :unless => %r{\A(https?://|xmpp:|gtalk:|mailto:)} }
19
+ #
20
+ # The key <tt>:scheme</tt> is always used as the prefix, when the input
21
+ # does not a match the regex in <tt>:unless</tt>.
7
22
  class UrlNormalizer < Normalizer
23
+
24
+ # Accepts either a hash or a string.
8
25
  def initialize(options = {})
9
26
  options = { :scheme => "http://", :unless => %r{\Ahttps?://}i } if options.nil? || options.empty?
10
27
  options = { :scheme => options, :unless => %r{\A#{options}}i } unless options.is_a?(Hash)
11
28
  super(options)
12
29
  end
13
30
 
31
+ # Prefixes input with <tt>options[:scheme]</tt> if it doesn't matches
32
+ # <tt>options[:unless]</tt>.
14
33
  def normalize_value(value)
34
+ value = super # just ensure that default stripping/cleaning is done already
35
+ return nil if value == options[:scheme]
15
36
  value =~ options[:unless] ? value : "#{options[:scheme]}#{value}" unless value.nil?
16
37
  end
17
38
  end
@@ -1,4 +1,4 @@
1
- module VacuumCleaner #:nodoc:
1
+ module VacuumCleaner
2
2
 
3
3
  # A small base class for implementing custom value normalizers.
4
4
  # Might seem like a slight overkill, yet makes the library pretty
@@ -46,7 +46,7 @@ module VacuumCleaner #:nodoc:
46
46
  # +normalize_value+.
47
47
  #
48
48
  # This can be used together with the +normalizes+ method (see
49
- # {{VacuumCleaner::Normalizers.normalizes}} for more on this).
49
+ # VacuumCleaner::Normalizers#normalizes for more on this).
50
50
  class Normalizer
51
51
  # Options as supplied to the normalizer.
52
52
  attr_reader :options
@@ -59,7 +59,7 @@ module VacuumCleaner #:nodoc:
59
59
  # Only override this method if access to the <tt>object</tt> or <tt>attribute</tt> name
60
60
  # is required, else override +normalize_value+, makes life much simpler :)
61
61
  #
62
- # Default behaviour just calls <tt>normalize_value(value)</tt>.
62
+ # Default behaviour just calls #normalize_value.
63
63
  def normalize(object, attribute, value); normalize_value(value) end
64
64
 
65
65
  # Override this method in subclasses to specifiy custom normalization steps and magic.
@@ -1,4 +1,3 @@
1
1
  require 'vacuum_cleaner'
2
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+
3
+ ActiveRecord::Base.class_eval { include VacuumCleaner::Normalizations } if defined?(ActiveRecord::Base) # all versions of rails
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ # load ActiveRecord
4
+ require 'active_record'
5
+
6
+ # open connection to in-memory db
7
+ ActiveRecord::Base.establish_connection({
8
+ :adapter => RUBY_PLATFORM =~ /java/ ? 'jdbcsqlite3' : 'sqlite3',
9
+ :database => ':memory:'})
10
+
11
+ # run init.rb
12
+ require File.join(File.dirname(__FILE__), '..', '..', 'init')
13
+
14
+ puts "Running integration tests against: active_record-#{ActiveRecord::VERSION::STRING}"
15
+
16
+ class ActiveRecordIntegrationTest < ::Test::Unit::TestCase
17
+ context "ActiveRecord::Base" do
18
+ should "include VacuumCleaner::Normalizations" do
19
+ assert ActiveRecord::Base.included_modules.include?(VacuumCleaner::Normalizations)
20
+ end
21
+
22
+ context "with a sqlite connection" do
23
+ setup do
24
+ # build db
25
+ ActiveRecord::Base.connection.create_table :dummies, :force => true do |t|
26
+ t.column :name, :string
27
+ end
28
+ end
29
+
30
+ should "respond to normalize and normalize :name on set" do
31
+ klass = Class.new(ActiveRecord::Base) do; set_table_name 'dummies'; normalizes :name end
32
+
33
+ object = klass.new({ :name => "Elliot Reid\n" })
34
+ assert_equal "Elliot Reid", object.name
35
+ end
36
+
37
+ should "normalize on +object.name+ accessors as well" do
38
+ klass = Class.new(ActiveRecord::Base) do; set_table_name 'dummies'; normalizes :name end
39
+
40
+ object = klass.new
41
+ object.name = " Dorian\t\n"
42
+ assert_equal "Dorian", object.name
43
+ end
44
+
45
+ should "not normalize when accessing directly using []/write_attribute" do
46
+ klass = Class.new(ActiveRecord::Base) do; set_table_name 'dummies'; normalizes :name end
47
+ object = klass.new
48
+ object[:name] = "Elliot Reid\n\t"
49
+ assert_equal "Elliot Reid\n\t", object.name
50
+ end
51
+
52
+ should "not normalize when reading from database" do
53
+ ActiveRecord::Base.connection.execute "INSERT INTO dummies VALUES(NULL,'Elliot Reid\n\t');"
54
+ klass = Class.new(ActiveRecord::Base) do; set_table_name 'dummies'; normalizes :name end
55
+ assert_equal "Elliot Reid\n\t", klass.last.name
56
+ end
57
+
58
+ should "work with customized setter methods, masking AR-attributes" do
59
+ klass = Class.new(ActiveRecord::Base) do; set_table_name 'dummies'; def name=(n); self[:name] = n; end; normalizes :name end
60
+ object = klass.new :name => " J.D.\n"
61
+ assert_equal "J.D.", object.name
62
+ object.name = "Dorian\n\r"
63
+ assert_equal "Dorian", object.name
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,10 +1,3 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
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 }
@@ -17,6 +17,11 @@ class VacuumCleaner::Normalizations::MethodTest < Test::Unit::TestCase
17
17
  assert_equal "ELLIOT\n", upcaser.normalize_value("Elliot\n")
18
18
  assert_equal " \t", upcaser.normalize_value(" \t")
19
19
  end
20
+
21
+ should "convert value to <nil> if object does not respond to supplied method" do
22
+ normalizer = MethodNormalizer.new(:this_method_does_certainly_not_exist)
23
+ assert_nil normalizer.normalize_value("Elliot")
24
+ end
20
25
  end
21
26
 
22
27
  context "DowncaseNormalizer#normalize_value" do
@@ -35,5 +35,14 @@ class VacuumCleaner::Normalizations::UrlTest < Test::Unit::TestCase
35
35
  assert_equal "jabber:jd@sh.com", n.normalize_value("jabber:jd@sh.com")
36
36
  assert_equal "https://docs.google.com", n.normalize_value("https://docs.google.com")
37
37
  end
38
+
39
+ should "normalize to <nil> if only scheme is given" do
40
+ assert_nil UrlNormalizer.new.normalize_value("http://")
41
+ assert_nil UrlNormalizer.new.normalize_value(" http://\n")
42
+ end
43
+
44
+ should "be stupid, so if some other scheme is used, just override it, haha" do
45
+ assert_equal "xmpp:mailto:jd@sacred-heart.com", UrlNormalizer.new("xmpp:").normalize_value("mailto:jd@sacred-heart.com")
46
+ end
38
47
  end
39
48
  end
metadata CHANGED
@@ -3,10 +3,10 @@ name: vacuum_cleaner
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
+ - 1
6
7
  - 0
7
- - 5
8
8
  - 0
9
- version: 0.5.0
9
+ version: 1.0.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Lukas Westermann
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-09 00:00:00 +01:00
17
+ date: 2010-04-21 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -31,24 +31,10 @@ dependencies:
31
31
  version: 2.10.2
32
32
  type: :development
33
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
34
  - !ruby/object:Gem::Dependency
49
35
  name: activesupport
50
36
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
37
+ requirement: &id002 !ruby/object:Gem::Requirement
52
38
  requirements:
53
39
  - - ">="
54
40
  - !ruby/object:Gem::Version
@@ -58,7 +44,7 @@ dependencies:
58
44
  - 5
59
45
  version: 2.3.5
60
46
  type: :development
61
- version_requirements: *id003
47
+ version_requirements: *id002
62
48
  description: Ruby (and Rails) attribute cleaning support, provides some nice and easy to enhance default normalization strategies.
63
49
  email: lukas.westermann@gmail.com
64
50
  executables: []
@@ -79,6 +65,7 @@ files:
79
65
  - lib/vacuum_cleaner/normalizations/url.rb
80
66
  - lib/vacuum_cleaner/normalizer.rb
81
67
  - rails/init.rb
68
+ - test/integration/active_record_integration_test.rb
82
69
  - test/test_helper.rb
83
70
  - test/unit/vacuum_cleaner/normalizations/method_test.rb
84
71
  - test/unit/vacuum_cleaner/normalizations/url_test.rb
@@ -115,6 +102,7 @@ signing_key:
115
102
  specification_version: 3
116
103
  summary: Ruby (and Rails) attribute cleaning support, provides some nice default normalization strategies.
117
104
  test_files:
105
+ - test/integration/active_record_integration_test.rb
118
106
  - test/test_helper.rb
119
107
  - test/unit/vacuum_cleaner/normalizations/method_test.rb
120
108
  - test/unit/vacuum_cleaner/normalizations/url_test.rb