data_cleansing 0.3.2 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8666401eb50e30f3b447a19d1764b6eb6ce34b70
4
- data.tar.gz: 4f039f29b178dd10071cb9b8ea97767e0a950250
3
+ metadata.gz: 2dfd8030076d210f31f5993ed3646abbe38934ea
4
+ data.tar.gz: a077de74aec84cb805e4087e4e6d04c5c8972a73
5
5
  SHA512:
6
- metadata.gz: f4949339d972ad1e361363dcf49b6cd6467eb2202c75e8751783818bbda85a31397d582fd9c6eaf72ccb29b379dd515e2dff8c2e07fe3a998d182cf7add187f6
7
- data.tar.gz: 9359a1fad55a8f47626c03925a8a956b3b5159624cb1fd6d987b7b3d2a6999c036d9d2677188a5f75ea8551d4d4094a17c351f8f0f1f6f2cf044115fab554008
6
+ metadata.gz: 9ee068df2896ee7ae1656fc8af6a4baf446b5969972dae873e62833689a3a110e546135a0cd8b37c23847374839aec79b9e12ef8d9c3baf138a1aaf85c00d47d
7
+ data.tar.gz: dac70b47e27ac5fbf4d96ae12570c071ebb694b69f0f039a798cf6d2a5e28a850845fd03879751eb2fb0eb1b6a11515f8163ee240763d5ac32d4f30d7d7797a2
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source 'https://rubygems.org'
2
+ gem 'thread_safe'
3
+ gem 'semantic_logger'
2
4
 
3
5
  group :test do
4
6
  gem "shoulda"
@@ -33,6 +33,9 @@ GEM
33
33
  leshill-will_paginate (>= 2.3.11)
34
34
  mongo (>= 0.18.2)
35
35
  multi_json (1.7.7)
36
+ semantic_logger (2.1.0)
37
+ sync_attr (>= 1.0)
38
+ thread_safe (>= 0.1.0)
36
39
  shoulda (3.5.0)
37
40
  shoulda-context (~> 1.0, >= 1.0.1)
38
41
  shoulda-matchers (>= 1.4.1, < 3.0)
@@ -40,6 +43,7 @@ GEM
40
43
  shoulda-matchers (2.2.0)
41
44
  activesupport (>= 3.0.0)
42
45
  sqlite3 (1.3.7)
46
+ sync_attr (1.0.0)
43
47
  thread_safe (0.1.0)
44
48
  atomic
45
49
  tzinfo (0.3.37)
@@ -53,5 +57,7 @@ DEPENDENCIES
53
57
  awesome_print
54
58
  jdbc-sqlite3
55
59
  mongoid
60
+ semantic_logger
56
61
  shoulda
57
62
  sqlite3
63
+ thread_safe
data/Rakefile CHANGED
@@ -24,6 +24,7 @@ task :gem do |t|
24
24
  s.license = "Apache License V2.0"
25
25
  s.has_rdoc = true
26
26
  s.add_dependency 'thread_safe'
27
+ s.add_dependency 'semantic_logger'
27
28
  end
28
29
  Gem::Package.build gemspec
29
30
  end
@@ -1,4 +1,5 @@
1
1
  require 'thread_safe'
2
+ require 'semantic_logger'
2
3
  require 'data_cleansing/version'
3
4
  require 'data_cleansing/data_cleansing'
4
5
 
@@ -7,11 +8,6 @@ module DataCleansing
7
8
  end
8
9
 
9
10
  # Rails Extensions
10
- #if defined?(Rails)
11
- # require 'data_cleansing/railtie'
12
- #end
13
-
14
- # Mongoid Extensions
15
- #if defined?(Mongoid)
16
- # require 'data_cleansing/extensions/mongoid/fields'
17
- #end
11
+ if defined?(Rails)
12
+ require 'data_cleansing/railtie'
13
+ end
@@ -1,102 +1,192 @@
1
1
  module DataCleansing
2
2
  # Mix-in to add cleaner
3
3
  module Cleanse
4
- CleanerStruct = Struct.new(:cleaners, :attributes, :params)
4
+ DataCleansingCleaner = Struct.new(:cleaners, :attributes, :params)
5
5
 
6
6
  module ClassMethods
7
7
  # Define how to cleanse one or more attributes
8
8
  def cleanse(*args)
9
9
  last = args.last
10
- params = (last.is_a?(Hash) && last.instance_of?(Hash)) ? args.pop.dup : {}
10
+ attributes = args.dup
11
+ params = (last.is_a?(Hash) && last.instance_of?(Hash)) ? attributes.pop.dup : {}
11
12
  cleaners = Array(params.delete(:cleaner))
12
13
  raise(ArgumentError, "Mandatory :cleaner parameter is missing: #{params.inspect}") unless cleaners
13
- (@cleaners ||= ThreadSafe::Array.new) << CleanerStruct.new(cleaners, args, params)
14
- nil
14
+ cleaner = DataCleansingCleaner.new(cleaners, attributes, params)
15
+ data_cleansing_cleaners << cleaner
16
+ attributes.each do |attr|
17
+ (data_cleansing_attribute_cleaners[attr] ||= ThreadSafe::Array.new) << cleaner
18
+ end
19
+ cleaner
20
+ end
21
+
22
+ # Returns the value cleansed using the cleaners defined for that attribute
23
+ # in this model and any of it's parents
24
+ #
25
+ # Parameters
26
+ # attribute_name
27
+ # Name of the attribute within this Class to be cleansed
28
+ # value
29
+ # Value to be cleansed
30
+ # object
31
+ # If supplied the cleansing will be performed within the scope of
32
+ # that object so that cleaners can read and write to attributes
33
+ # of that object
34
+ #
35
+ # Warning: If any of the cleaners read or write to other object attributes
36
+ # then a valid object instance must be supplied
37
+ def cleanse_attribute(attribute_name, value, object=nil)
38
+ return if value.nil?
39
+
40
+ # Collect parent cleaners first, starting with the top parent
41
+ cleaners = []
42
+ klass = self
43
+ while klass != Object
44
+ if klass.respond_to?(:data_cleansing_attribute_cleaners)
45
+ cleaners += klass.data_cleansing_attribute_cleaners[:all] || []
46
+ cleaners += klass.data_cleansing_attribute_cleaners[attribute_name.to_sym] || []
47
+ end
48
+ klass = klass.superclass
49
+ end
50
+ cleansed_value = value.dup
51
+ cleaners.reverse_each {|cleaner| cleansed_value = data_cleansing_clean(cleaner, cleansed_value, object) if cleaner}
52
+ cleansed_value
15
53
  end
16
54
 
17
- def cleaners
18
- @cleaners
55
+ # Array of cleaners to execute against this model and it's children
56
+ def data_cleansing_cleaners
57
+ @data_cleansing_cleaners ||= ThreadSafe::Array.new
58
+ end
59
+
60
+ # Hash of attributes to clean with their corresponding cleaner
61
+ def data_cleansing_attribute_cleaners
62
+ @data_cleansing_attribute_cleaners ||= ThreadSafe::Hash.new
63
+ end
64
+
65
+ private
66
+
67
+ # Returns the supplied value cleansed using the supplied cleaner
68
+ # Parameters
69
+ # object
70
+ # If supplied the cleansing will be performed within the scope of
71
+ # that object so that cleaners can read and write to attributes
72
+ # of that object
73
+ #
74
+ # No logging of cleansing is performed by this method since the value
75
+ # itself is not modified
76
+ def data_cleansing_clean(cleaner_struct, value, object=nil)
77
+ return if cleaner_struct.nil? || value.nil?
78
+ # Duplicate value in case cleaner uses methods such as gsub!
79
+ new_value = value.is_a?(String) ? value.dup : value
80
+ cleaner_struct.cleaners.each do |cleaner|
81
+ # Cleaner itself could be a custom Proc, otherwise do a global lookup for it
82
+ proc = cleaner.is_a?(Proc) ? cleaner : DataCleansing.cleaner(cleaner.to_sym)
83
+ raise "No cleaner defined for #{cleaner.inspect}" unless proc
84
+
85
+ new_value = if object
86
+ # Call the cleaner proc within the scope (binding) of the object
87
+ proc.arity == 1 ? object.instance_exec(new_value, &proc) : object.instance_exec(new_value, cleaner_struct.params, &proc)
88
+ else
89
+ proc.arity == 1 ? proc.call(new_value) : proc.call(new_value, cleaner_struct.params)
90
+ end
91
+ end
92
+ new_value
19
93
  end
94
+
20
95
  end
21
96
 
22
97
  module InstanceMethods
23
98
  # Cleanse the attributes using specified cleaners
24
99
  def cleanse_attributes!
25
- # Execute parent cleansers first, starting with the top parent
26
- klasses = [self.class]
100
+ # Collect parent cleaners first, starting with the top parent
101
+ cleaners = [self.class.send(:data_cleansing_cleaners)]
27
102
  klass = self.class.superclass
28
103
  while klass != Object
29
- klasses << klass if klass.respond_to?(:cleaners)
104
+ cleaners << klass.send(:data_cleansing_cleaners) if klass.respond_to?(:data_cleansing_cleaners)
30
105
  klass = klass.superclass
31
106
  end
32
- klasses.reverse_each {|klass| execute_cleaners(klass.cleaners)}
107
+ cleaners.reverse_each {|cleaner| data_cleansing_execute_cleaners(cleaner)}
33
108
  true
34
109
  end
35
110
 
36
111
  private
37
112
 
38
113
  # Run each of the cleaners in the order they are listed in the array
39
- def execute_cleaners(cleaners)
114
+ def data_cleansing_execute_cleaners(cleaners)
40
115
  return false if cleaners.nil?
41
- cleaners.each do |cleaner_struct|
42
- params = cleaner_struct.params
43
- attrs = cleaner_struct.attributes
44
-
45
- # Special case to include :all fields
46
- # Only works with ActiveRecord based models, not supported with regular Ruby models
47
- if attrs.include?(:all) && defined?(ActiveRecord) && respond_to?(:attributes)
48
- attrs = attributes.keys.collect{|i| i.to_sym}
49
- attrs.delete(:id)
50
-
51
- # Remove serialized_attributes if any, from the :all condition
52
- if self.class.respond_to?(:serialized_attributes)
53
- serialized_attrs = self.class.serialized_attributes.keys
54
- attrs -= serialized_attrs.collect{|i| i.to_sym} if serialized_attrs
55
- end
56
116
 
57
- # Replace any encrypted attributes with their non-encrypted versions if any
58
- if defined?(SymmetricEncryption) && self.class.respond_to?(:encrypted_attributes)
59
- self.class.encrypted_attributes.each_pair do |clear, encrypted|
60
- if attrs.include?(encrypted.to_sym)
61
- attrs.delete(encrypted.to_sym)
62
- attrs << clear.to_sym
63
- end
117
+ # Capture all changes to attributes if the log level is high enough
118
+ changes = {} if DataCleansing.logger.send("#{DataCleansing.cleansing_log_level}?")
119
+
120
+ #logger.send(self.class.data_cleansing_log_level, "Cleansed Attributes", changes) if changes
121
+ DataCleansing.logger.send("benchmark_#{DataCleansing.cleansing_log_level}","Cleansed Attributes", :payload => changes) do
122
+ cleaners.each do |cleaner_struct|
123
+ params = cleaner_struct.params
124
+ attrs = cleaner_struct.attributes
125
+
126
+ # Special case to include :all fields
127
+ # Only works with ActiveRecord based models, not supported with regular Ruby models
128
+ if attrs.include?(:all) && defined?(ActiveRecord) && respond_to?(:attributes)
129
+ attrs = attributes.keys.collect{|i| i.to_sym}
130
+ attrs.delete(:id)
131
+
132
+ # Remove serialized_attributes if any, from the :all condition
133
+ if self.class.respond_to?(:serialized_attributes)
134
+ serialized_attrs = self.class.serialized_attributes.keys
135
+ attrs -= serialized_attrs.collect{|i| i.to_sym} if serialized_attrs
64
136
  end
65
- end
66
137
 
67
- # Explicitly remove specified attributes from cleansing
68
- if except = params[:except]
69
- attrs -= except
70
- end
138
+ # Replace any encrypted attributes with their non-encrypted versions if any
139
+ if defined?(SymmetricEncryption) && self.class.respond_to?(:encrypted_attributes)
140
+ self.class.encrypted_attributes.each_pair do |clear, encrypted|
141
+ if attrs.include?(encrypted.to_sym)
142
+ attrs.delete(encrypted.to_sym)
143
+ attrs << clear.to_sym
144
+ end
145
+ end
146
+ end
71
147
 
72
- end
148
+ # Explicitly remove specified attributes from cleansing
149
+ if except = params[:except]
150
+ attrs -= except
151
+ end
73
152
 
74
- attrs.each do |attr|
75
- # Under ActiveModel for Rails and Mongoid need to retrieve raw value
76
- # before data type conversion
77
- value = if respond_to?(:read_attribute_before_type_cast) && has_attribute?(attr.to_s)
78
- read_attribute_before_type_cast(attr.to_s)
79
- else
80
- send(attr.to_sym)
81
153
  end
82
154
 
83
- # No need to clean if attribute is nil
84
- unless value.nil?
85
- # Allow multiple cleaners to be defined and only set the new value
86
- # once all cleaners have run
87
- new_value = value
88
- cleaner_struct.cleaners.each do |cleaner|
89
- # Cleaner itself could be a custom Proc, otherwise do a global lookup for it
90
- proc = cleaner.is_a?(Proc) ? cleaner : DataCleansing.cleaner(cleaner.to_sym)
91
- raise "No cleaner defined for #{cleaner.inspect}" unless proc
92
-
93
- # Call the cleaner proc within the scope (binding) of this object
94
- new_value = instance_exec(new_value, params, &proc)
155
+ attrs.each do |attr|
156
+ # Under ActiveModel for Rails and Mongoid need to retrieve raw value
157
+ # before data type conversion
158
+ value = if respond_to?(:read_attribute_before_type_cast) && has_attribute?(attr.to_s)
159
+ read_attribute_before_type_cast(attr.to_s)
160
+ else
161
+ send(attr.to_sym)
95
162
  end
96
- # Update value if it has changed
97
- send("#{attr.to_sym}=".to_sym, new_value) if new_value != value
98
- end
99
163
 
164
+ # No need to clean if attribute is nil
165
+ unless value.nil?
166
+ new_value = self.class.send(:data_cleansing_clean,cleaner_struct, value, self)
167
+
168
+ if new_value != value
169
+ # Update value only if it has changed
170
+ send("#{attr.to_sym}=".to_sym, new_value)
171
+
172
+ # Capture changed attributes
173
+ if changes
174
+ # Mask sensitive attributes when logging
175
+ masked = DataCleansing.masked_attributes.include?(attr.to_sym)
176
+ new_value = :masked if masked && !new_value.nil?
177
+ if previous = changes[attr.to_sym]
178
+ previous[:after] = new_value
179
+ else
180
+ changes[attr.to_sym] = {
181
+ :before => masked ? :masked : value,
182
+ :after => new_value
183
+ }
184
+ end
185
+ end
186
+ end
187
+ end
188
+
189
+ end
100
190
  end
101
191
  end
102
192
  nil
@@ -105,8 +195,8 @@ module DataCleansing
105
195
 
106
196
  def self.included(base)
107
197
  base.class_eval do
108
- extend(DataCleansing::Cleanse::ClassMethods)
109
- include(DataCleansing::Cleanse::InstanceMethods)
198
+ extend DataCleansing::Cleanse::ClassMethods
199
+ include DataCleansing::Cleanse::InstanceMethods
110
200
  end
111
201
  end
112
202
  end
@@ -1,23 +1,41 @@
1
1
  module DataCleansing
2
+ include SemanticLogger::Loggable
2
3
 
3
4
  # Global Data Cleansers
4
- @@global_cleaners = ThreadSafe::Hash.new
5
+ @@global_cleaners = ThreadSafe::Hash.new
6
+ @@masked_attributes = ThreadSafe::Array.new
7
+ @@cleansing_log_level = :info
5
8
 
6
9
  # Register a new cleaner
7
10
  # Replaces any existing cleaner with the same name
8
11
  def self.register_cleaner(cleaner, &block)
9
- if block
10
- @@global_cleaners[cleaner.to_sym] = block
11
- else
12
- # TODO Expose class methods as cleaners
13
- #
14
- # cleaners[cleaner.to_sym] = block
15
- # raise ArgumentError, "Must supply either a Proc, or a cleaner klass"
16
- end
12
+ raise "Must supply a Proc with the cleaner" unless block
13
+ @@global_cleaners[cleaner.to_sym] = block
17
14
  end
18
15
 
19
16
  # Returns the cleaner matching the supplied cleaner name
20
17
  def self.cleaner(cleaner_name)
21
18
  @@global_cleaners[cleaner_name.to_sym]
22
19
  end
20
+
21
+ # Register Attributes to be masked out in any log output
22
+ def self.register_masked_attributes(*attributes)
23
+ attributes.each {|attr| @@masked_attributes << attr.to_sym }
24
+ end
25
+
26
+ # Returns the Global list of attributes to mask in any log output
27
+ def self.masked_attributes
28
+ @@masked_attributes.freeze
29
+ end
30
+
31
+ # Set the log_level at which to log cleansing activities at
32
+ def self.cleansing_log_level
33
+ @@cleansing_log_level
34
+ end
35
+
36
+ # Set the log_level at which to log cleansing activities at
37
+ def self.cleansing_log_level=(log_level)
38
+ @@cleansing_log_level = log_level
39
+ end
40
+
23
41
  end
@@ -0,0 +1,16 @@
1
+ module RubySkynet #:nodoc:
2
+ class Railtie < Rails::Railtie #:nodoc:
3
+
4
+ # Exposes DataCleansing configuration to the Rails application configuration.
5
+ #
6
+ # @example Set up configuration in the Rails app.
7
+ # module MyApplication
8
+ # class Application < Rails::Application
9
+ # config.data_cleansing.masked_attributes :bank_account_number, :social_security_number
10
+ # config.data_cleansing.cleansing_log_level :info
11
+ # config.data_cleansing.register_cleaner(:strip) {|string| string.strip!}
12
+ # end
13
+ # end
14
+ config.data_cleansing = ::DataCleansing
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module DataCleansing
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -8,8 +8,13 @@ require 'shoulda'
8
8
  # are loaded
9
9
  require 'active_record'
10
10
  require 'data_cleansing'
11
+ require 'semantic_logger'
11
12
 
12
- ActiveRecord::Base.logger = Logger.new($stderr)
13
+ # Register an appender if one is not already registered
14
+ SemanticLogger.default_level = :trace
15
+ SemanticLogger.add_appender('test.log') if SemanticLogger.appenders.size == 0
16
+
17
+ ActiveRecord::Base.logger = SemanticLogger[ActiveRecord::Base]
13
18
  ActiveRecord::Base.configurations = {
14
19
  'test' => {
15
20
  'adapter' => 'sqlite3',
@@ -26,6 +31,7 @@ ActiveRecord::Schema.define :version => 0 do
26
31
  t.string :last_name
27
32
  t.string :address1
28
33
  t.string :address2
34
+ t.string :ssn
29
35
  t.integer :zip_code
30
36
  end
31
37
  end
@@ -33,6 +39,13 @@ end
33
39
  # Define a global cleaner
34
40
  DataCleansing.register_cleaner(:strip) {|string, params, object| string.strip!}
35
41
 
42
+ # Log data cleansing result at :info level
43
+ # Set to a level below the current log level to disable
44
+ DataCleansing.cleansing_log_level = :info
45
+
46
+ # Set the Global list of fields to be masked
47
+ DataCleansing.register_masked_attributes :ssn, :bank_account_number
48
+
36
49
  # Removes all non-digit characters, except '.' then truncates
37
50
  # the result to an integer string
38
51
  # Returns nil if no digits are present in the string
@@ -74,6 +87,15 @@ class User2 < ActiveRecord::Base
74
87
  # Test :all cleaner. Only works with ActiveRecord Models
75
88
  cleanse :all, :cleaner => [:strip, Proc.new{|s| "@#{s}@"}], :except => [:address1, :zip_code]
76
89
 
90
+ # Clean :first_name multiple times
91
+ cleanse :first_name, :cleaner => Proc.new {|string| "<< #{string} >>"}
92
+
93
+ # Clean :first_name multiple times
94
+ cleanse :first_name, :cleaner => Proc.new {|string| "$#{string}$"}
95
+
96
+ # Custom Zip Code cleaner
97
+ cleanse :zip_code, :cleaner => :digits_to_integer
98
+
77
99
  # Automatically cleanse data before validation
78
100
  before_validation :cleanse_attributes!
79
101
  end
@@ -85,19 +107,27 @@ class ActiveRecordTest < Test::Unit::TestCase
85
107
  assert DataCleansing.cleaner(:strip)
86
108
  end
87
109
 
110
+ should 'Model.cleanse_attribute' do
111
+ assert_equal 'joe', User.cleanse_attribute(:first_name, ' joe ')
112
+ assert_equal 'black', User.cleanse_attribute(:last_name, "\n black\n")
113
+ assert_equal '<< 2632 Brown St >>', User.cleanse_attribute(:address1, "2632 Brown St \n")
114
+ assert_equal '<< instance >>', User.cleanse_attribute(:instance_var, "\n instance\n\t ")
115
+ assert_equal 12345, User.cleanse_attribute(:zip_code, "\n\tblah 12345badtext\n")
116
+ end
117
+
88
118
  context "with user" do
89
119
  setup do
90
120
  @user = User.new(
91
- :first_name => ' joe ',
92
- :last_name => "\n black\n",
93
- :address1 => "2632 Brown St \n",
94
- :zip_code => "\n\tblah 12345badtext\n",
121
+ :first_name => ' joe ',
122
+ :last_name => "\n black\n",
123
+ :address1 => "2632 Brown St \n",
124
+ :zip_code => "\n\tblah 12345badtext\n",
95
125
  :instance_var => "\n instance\n\t "
96
126
  )
97
127
  end
98
128
 
99
129
  should 'only have 3 cleaners' do
100
- assert_equal 3, User.cleaners.size, User.cleaners
130
+ assert_equal 3, User.send(:data_cleansing_cleaners).size, User.send(:data_cleansing_cleaners)
101
131
  end
102
132
 
103
133
  should 'cleanse_attributes! using global cleaner' do
@@ -123,21 +153,28 @@ class ActiveRecordTest < Test::Unit::TestCase
123
153
  @user = User2.new(
124
154
  :first_name => ' joe ',
125
155
  :last_name => "\n black\n",
156
+ :ssn => "\n 123456789 \n ",
126
157
  :address1 => "2632 Brown St \n",
127
- :zip_code => "\n\t12345\n"
158
+ :zip_code => "\n\t blah\n"
128
159
  )
129
160
  end
130
161
 
131
- should 'only have 1 cleaner' do
132
- assert_equal 1, User2.cleaners.size, User2.cleaners
162
+ should 'have 4 cleaners defined' do
163
+ assert_equal 4, User2.send(:data_cleansing_cleaners).size, User2.send(:data_cleansing_cleaners)
164
+ end
165
+
166
+ should 'have 3 attributes cleaners defined' do
167
+ # :all, :first_name, :zip_code
168
+ assert_equal 3, User2.send(:data_cleansing_attribute_cleaners).size, User2.send(:data_cleansing_attribute_cleaners)
133
169
  end
134
170
 
135
171
  should 'cleanse_attributes! clean all attributes' do
136
172
  assert_equal true, @user.valid?
137
- assert_equal '@joe@', @user.first_name, User2.cleaners
173
+ assert_equal '$<< @joe@ >>$', @user.first_name, User2.send(:data_cleansing_cleaners)
138
174
  assert_equal '@black@', @user.last_name
139
175
  assert_equal "2632 Brown St \n", @user.address1
140
- assert_equal 12345, @user.zip_code, User2.cleaners
176
+ assert_equal "@123456789@", @user.ssn
177
+ assert_equal nil, @user.zip_code, User2.send(:data_cleansing_cleaners)
141
178
  end
142
179
 
143
180
  end
@@ -70,6 +70,13 @@ class RubyTest < Test::Unit::TestCase
70
70
  assert DataCleansing.cleaner(:strip)
71
71
  end
72
72
 
73
+ should 'Model.cleanse_attribute' do
74
+ assert_equal 'male', RubyUserChild.cleanse_attribute(:gender, "\n Male \n"), RubyUserChild.send(:data_cleansing_attribute_cleaners)
75
+ assert_equal 'joe', RubyUserChild.cleanse_attribute(:first_name, ' joe '), RubyUserChild.send(:data_cleansing_attribute_cleaners)
76
+ assert_equal 'black', RubyUserChild.cleanse_attribute(:last_name, "\n black\n"), RubyUserChild.send(:data_cleansing_attribute_cleaners)
77
+ assert_equal '<< 2632 Brown St >>', RubyUserChild.cleanse_attribute(:address1, "2632 Brown St \n"), RubyUserChild.send(:data_cleansing_attribute_cleaners)
78
+ end
79
+
73
80
  context "with ruby user" do
74
81
  setup do
75
82
  @user = RubyUser.new
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_cleansing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-19 00:00:00.000000000 Z
11
+ date: 2013-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread_safe
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: semantic_logger
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: Data Cleansing framework for Ruby with additional support for Rails and
28
42
  Mongoid
29
43
  email:
@@ -40,6 +54,7 @@ files:
40
54
  - lib/data_cleansing.rb
41
55
  - lib/data_cleansing/cleanse.rb
42
56
  - lib/data_cleansing/data_cleansing.rb
57
+ - lib/data_cleansing/railtie.rb
43
58
  - lib/data_cleansing/version.rb
44
59
  - nbproject/private/private.properties
45
60
  - nbproject/private/private.xml