data_cleansing 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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