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 +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +6 -0
- data/Rakefile +1 -0
- data/lib/data_cleansing.rb +4 -8
- data/lib/data_cleansing/cleanse.rb +153 -63
- data/lib/data_cleansing/data_cleansing.rb +27 -9
- data/lib/data_cleansing/railtie.rb +16 -0
- data/lib/data_cleansing/version.rb +1 -1
- data/test/active_record_test.rb +48 -11
- data/test/ruby_test.rb +7 -0
- data/test/test_db.sqlite3 +0 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dfd8030076d210f31f5993ed3646abbe38934ea
|
4
|
+
data.tar.gz: a077de74aec84cb805e4087e4e6d04c5c8972a73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ee068df2896ee7ae1656fc8af6a4baf446b5969972dae873e62833689a3a110e546135a0cd8b37c23847374839aec79b9e12ef8d9c3baf138a1aaf85c00d47d
|
7
|
+
data.tar.gz: dac70b47e27ac5fbf4d96ae12570c071ebb694b69f0f039a798cf6d2a5e28a850845fd03879751eb2fb0eb1b6a11515f8163ee240763d5ac32d4f30d7d7797a2
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -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
data/lib/data_cleansing.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
18
|
-
|
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
|
-
#
|
26
|
-
|
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
|
-
|
104
|
+
cleaners << klass.send(:data_cleansing_cleaners) if klass.respond_to?(:data_cleansing_cleaners)
|
30
105
|
klass = klass.superclass
|
31
106
|
end
|
32
|
-
|
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
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
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
|
-
|
84
|
-
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
109
|
-
include
|
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
|
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
|
-
|
10
|
-
|
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
|
data/test/active_record_test.rb
CHANGED
@@ -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
|
-
|
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
|
92
|
-
:last_name
|
93
|
-
:address1
|
94
|
-
:zip_code
|
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.
|
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\
|
158
|
+
:zip_code => "\n\t blah\n"
|
128
159
|
)
|
129
160
|
end
|
130
161
|
|
131
|
-
should '
|
132
|
-
assert_equal
|
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.
|
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
|
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
|
data/test/ruby_test.rb
CHANGED
@@ -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
|
data/test/test_db.sqlite3
CHANGED
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.
|
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-
|
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
|