attr_encrypted-magicless 1.3.42

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.
@@ -0,0 +1,339 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path('../test_helper', __FILE__)
3
+
4
+ class SillyEncryptor
5
+ def self.silly_encrypt(options)
6
+ (options[:value] + options[:some_arg]).reverse
7
+ end
8
+
9
+ def self.silly_decrypt(options)
10
+ options[:value].reverse.gsub(/#{options[:some_arg]}$/, '')
11
+ end
12
+ end
13
+
14
+ class User
15
+ include AttrEncrypted
16
+
17
+ self.attr_encrypted_options[:key] = Proc.new { |user| SECRET_KEY } # default key
18
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
19
+
20
+ attr_encrypted :email, :without_encoding, :key => SECRET_KEY
21
+ attr_encrypted :password, :prefix => 'crypted_', :suffix => '_test'
22
+ attr_encrypted :ssn, :key => :secret_key, :attribute => 'ssn_encrypted'
23
+ attr_encrypted :credit_card, :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt, :some_arg => 'test'
24
+ attr_encrypted :with_encoding, :key => SECRET_KEY, :encode => true
25
+ attr_encrypted :with_custom_encoding, :key => SECRET_KEY, :encode => 'm'
26
+ attr_encrypted :with_marshaling, :key => SECRET_KEY, :marshal => true
27
+ attr_encrypted :with_true_if, :key => SECRET_KEY, :if => true
28
+ attr_encrypted :with_false_if, :key => SECRET_KEY, :if => false
29
+ attr_encrypted :with_true_unless, :key => SECRET_KEY, :unless => true
30
+ attr_encrypted :with_false_unless, :key => SECRET_KEY, :unless => false
31
+ attr_encrypted :with_if_changed, :key => SECRET_KEY, :if => :should_encrypt
32
+
33
+ attr_encryptor :aliased, :key => SECRET_KEY
34
+
35
+ attr_accessor :salt
36
+ attr_accessor :should_encrypt
37
+
38
+ def initialize
39
+ self.salt = Time.now.to_i.to_s
40
+ self.should_encrypt = true
41
+ end
42
+
43
+ def secret_key
44
+ SECRET_KEY
45
+ end
46
+ end
47
+
48
+ class Admin < User
49
+ attr_encrypted :testing
50
+ end
51
+
52
+ class SomeOtherClass
53
+ include AttrEncrypted
54
+
55
+ def self.call(object)
56
+ object.class
57
+ end
58
+ end
59
+
60
+ class CryptedObject
61
+ include AttrEncrypted
62
+ end
63
+
64
+ class AttrEncryptedTest < Minitest::Test
65
+
66
+ def test_should_store_email_in_encrypted_attributes
67
+ assert User.encrypted_attributes.include?(:email)
68
+ end
69
+
70
+ def test_should_not_store_salt_in_encrypted_attributes
71
+ assert !User.encrypted_attributes.include?(:salt)
72
+ end
73
+
74
+ def test_attr_encrypted_should_return_true_for_email
75
+ assert User.attr_encrypted?('email')
76
+ end
77
+
78
+ def test_attr_encrypted_should_not_use_the_same_attribute_name_for_two_attributes_in_the_same_line
79
+ refute_equal User.encrypted_attributes[:email][:attribute], User.encrypted_attributes[:without_encoding][:attribute]
80
+ end
81
+
82
+ def test_attr_encrypted_should_return_false_for_salt
83
+ assert !User.attr_encrypted?('salt')
84
+ end
85
+
86
+ def test_should_generate_an_encrypted_attribute
87
+ assert User.new.respond_to?(:encrypted_email)
88
+ end
89
+
90
+ def test_should_generate_an_encrypted_attribute_with_a_prefix_and_suffix
91
+ assert User.new.respond_to?(:crypted_password_test)
92
+ end
93
+
94
+ def test_should_generate_an_encrypted_attribute_with_the_attribute_option
95
+ assert User.new.respond_to?(:ssn_encrypted)
96
+ end
97
+
98
+ def test_should_not_encrypt_nil_value
99
+ assert_nil User.encrypt_email(nil)
100
+ end
101
+
102
+ def test_should_not_encrypt_empty_string
103
+ assert_equal '', User.encrypt_email('')
104
+ end
105
+
106
+ def test_should_encrypt_email
107
+ refute_nil User.encrypt_email('test@example.com')
108
+ refute_equal 'test@example.com', User.encrypt_email('test@example.com')
109
+ end
110
+
111
+ def test_should_encrypt_email_when_modifying_the_attr_writer
112
+ @user = User.new
113
+ assert_nil @user.encrypted_email
114
+ @user.email = 'test@example.com'
115
+ refute_nil @user.encrypted_email
116
+ assert_equal User.encrypt_email('test@example.com'), @user.encrypted_email
117
+ end
118
+
119
+ def test_should_not_decrypt_nil_value
120
+ assert_nil User.decrypt_email(nil)
121
+ end
122
+
123
+ def test_should_not_decrypt_empty_string
124
+ assert_equal '', User.decrypt_email('')
125
+ end
126
+
127
+ def test_should_decrypt_email
128
+ encrypted_email = User.encrypt_email('test@example.com')
129
+ refute_equal 'test@test.com', encrypted_email
130
+ assert_equal 'test@example.com', User.decrypt_email(encrypted_email)
131
+ end
132
+
133
+ def test_should_decrypt_email_when_reading
134
+ @user = User.new
135
+ assert_nil @user.email
136
+ @user.encrypted_email = User.encrypt_email('test@example.com')
137
+ assert_equal 'test@example.com', @user.email
138
+ end
139
+
140
+ def test_should_encrypt_with_encoding
141
+ assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
142
+ end
143
+
144
+ def test_should_decrypt_with_encoding
145
+ encrypted = User.encrypt_with_encoding('test')
146
+ assert_equal 'test', User.decrypt_with_encoding(encrypted)
147
+ assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
148
+ end
149
+
150
+ def test_should_encrypt_with_custom_encoding
151
+ assert_equal User.encrypt_with_encoding('test'), [User.encrypt_without_encoding('test')].pack('m')
152
+ end
153
+
154
+ def test_should_decrypt_with_custom_encoding
155
+ encrypted = User.encrypt_with_encoding('test')
156
+ assert_equal 'test', User.decrypt_with_encoding(encrypted)
157
+ assert_equal User.decrypt_with_encoding(encrypted), User.decrypt_without_encoding(encrypted.unpack('m').first)
158
+ end
159
+
160
+ def test_should_encrypt_with_marshaling
161
+ @user = User.new
162
+ @user.with_marshaling = [1, 2, 3]
163
+ refute_nil @user.encrypted_with_marshaling
164
+ end
165
+
166
+ def test_should_use_custom_encryptor_and_crypt_method_names_and_arguments
167
+ assert_equal SillyEncryptor.silly_encrypt(:value => 'testing', :some_arg => 'test'), User.encrypt_credit_card('testing')
168
+ end
169
+
170
+ def test_should_evaluate_a_key_passed_as_a_symbol
171
+ @user = User.new
172
+ assert_nil @user.ssn_encrypted
173
+ @user.ssn = 'testing'
174
+ refute_nil @user.ssn_encrypted
175
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.ssn_encrypted_iv.unpack("m").first, :salt => @user.ssn_encrypted_salt )
176
+ assert_equal encrypted, @user.ssn_encrypted
177
+ end
178
+
179
+ def test_should_evaluate_a_key_passed_as_a_proc
180
+ @user = User.new
181
+ assert_nil @user.crypted_password_test
182
+ @user.password = 'testing'
183
+ refute_nil @user.crypted_password_test
184
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
185
+ assert_equal encrypted, @user.crypted_password_test
186
+ end
187
+
188
+ def test_should_use_options_found_in_the_attr_encrypted_options_attribute
189
+ @user = User.new
190
+ assert_nil @user.crypted_password_test
191
+ @user.password = 'testing'
192
+ refute_nil @user.crypted_password_test
193
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.crypted_password_test_iv.unpack("m").first, :salt => @user.crypted_password_test_salt)
194
+ assert_equal encrypted, @user.crypted_password_test
195
+ end
196
+
197
+ def test_should_inherit_encrypted_attributes
198
+ assert_equal [User.encrypted_attributes.keys, :testing].flatten.collect { |key| key.to_s }.sort, Admin.encrypted_attributes.keys.collect { |key| key.to_s }.sort
199
+ end
200
+
201
+ def test_should_inherit_attr_encrypted_options
202
+ assert !User.attr_encrypted_options.empty?
203
+ assert_equal User.attr_encrypted_options, Admin.attr_encrypted_options
204
+ end
205
+
206
+ def test_should_not_inherit_unrelated_attributes
207
+ assert SomeOtherClass.attr_encrypted_options.empty?
208
+ assert SomeOtherClass.encrypted_attributes.empty?
209
+ end
210
+
211
+ def test_should_evaluate_a_symbol_option
212
+ assert_equal CryptedObject, CryptedObject.new.send(:evaluate_attr_encrypted_option, :class)
213
+ end
214
+
215
+ def test_should_evaluate_a_proc_option
216
+ assert_equal CryptedObject, CryptedObject.new.send(:evaluate_attr_encrypted_option, proc { |object| object.class })
217
+ end
218
+
219
+ def test_should_evaluate_a_lambda_option
220
+ assert_equal CryptedObject, CryptedObject.new.send(:evaluate_attr_encrypted_option, lambda { |object| object.class })
221
+ end
222
+
223
+ def test_should_evaluate_a_method_option
224
+ assert_equal CryptedObject, CryptedObject.new.send(:evaluate_attr_encrypted_option, SomeOtherClass.method(:call))
225
+ end
226
+
227
+ def test_should_return_a_string_option
228
+ assert_equal 'CryptedObject', CryptedObject.new.send(:evaluate_attr_encrypted_option, 'CryptedObject')
229
+ end
230
+
231
+ def test_should_encrypt_with_true_if
232
+ @user = User.new
233
+ assert_nil @user.encrypted_with_true_if
234
+ @user.with_true_if = 'testing'
235
+ refute_nil @user.encrypted_with_true_if
236
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_true_if_iv.unpack("m").first, :salt => @user.encrypted_with_true_if_salt)
237
+ assert_equal encrypted, @user.encrypted_with_true_if
238
+ end
239
+
240
+ def test_should_not_encrypt_with_false_if
241
+ @user = User.new
242
+ assert_nil @user.encrypted_with_false_if
243
+ @user.with_false_if = 'testing'
244
+ refute_nil @user.encrypted_with_false_if
245
+ assert_equal 'testing', @user.encrypted_with_false_if
246
+ end
247
+
248
+ def test_should_encrypt_with_false_unless
249
+ @user = User.new
250
+ assert_nil @user.encrypted_with_false_unless
251
+ @user.with_false_unless = 'testing'
252
+ refute_nil @user.encrypted_with_false_unless
253
+ encrypted = Encryptor.encrypt(:value => 'testing', :key => SECRET_KEY, :iv => @user.encrypted_with_false_unless_iv.unpack("m").first, :salt => @user.encrypted_with_false_unless_salt)
254
+ assert_equal encrypted, @user.encrypted_with_false_unless
255
+ end
256
+
257
+ def test_should_not_encrypt_with_true_unless
258
+ @user = User.new
259
+ assert_nil @user.encrypted_with_true_unless
260
+ @user.with_true_unless = 'testing'
261
+ refute_nil @user.encrypted_with_true_unless
262
+ assert_equal 'testing', @user.encrypted_with_true_unless
263
+ end
264
+
265
+ def test_should_work_with_aliased_attr_encryptor
266
+ assert User.encrypted_attributes.include?(:aliased)
267
+ end
268
+
269
+ def test_should_always_reset_options
270
+ @user = User.new
271
+ @user.with_if_changed = "encrypt_stuff"
272
+ @user.stubs(:instance_variable_get).returns(nil)
273
+ @user.stubs(:instance_variable_set).raises("BadStuff")
274
+ assert_raises RuntimeError do
275
+ @user.with_if_changed
276
+ end
277
+
278
+ @user = User.new
279
+ @user.should_encrypt = false
280
+ @user.with_if_changed = "not_encrypted_stuff"
281
+ assert_equal "not_encrypted_stuff", @user.with_if_changed
282
+ assert_equal "not_encrypted_stuff", @user.encrypted_with_if_changed
283
+ end
284
+
285
+ def test_should_cast_values_as_strings_before_encrypting
286
+ string_encrypted_email = User.encrypt_email('3')
287
+ assert_equal string_encrypted_email, User.encrypt_email(3)
288
+ assert_equal '3', User.decrypt_email(string_encrypted_email)
289
+ end
290
+
291
+ def test_should_create_query_accessor
292
+ @user = User.new
293
+ assert !@user.email?
294
+ @user.email = ''
295
+ assert !@user.email?
296
+ @user.email = 'test@example.com'
297
+ assert @user.email?
298
+ end
299
+
300
+ def test_should_vary_iv_per_attribute
301
+ @user = User.new
302
+ @user.email = 'email@example.com'
303
+ @user.password = 'p455w0rd'
304
+ refute_equal @user.encrypted_email_iv, @user.crypted_password_test_iv
305
+ end
306
+
307
+ def test_should_vary_iv_per_instance
308
+ @user1 = User.new
309
+ @user1.email = 'email@example.com'
310
+ @user2 = User.new
311
+ @user2.email = 'email@example.com'
312
+ refute_equal @user1.encrypted_email_iv, @user2.encrypted_email_iv
313
+ end
314
+
315
+ def test_should_vary_salt_per_attribute
316
+ @user = User.new
317
+ @user.email = 'email@example.com'
318
+ @user.password = 'p455w0rd'
319
+ refute_equal @user.encrypted_email_salt, @user.crypted_password_test_salt
320
+ end
321
+
322
+ def test_should_vary_salt_per_instance
323
+ @user1 = User.new
324
+ @user1.email = 'email@example.com'
325
+ @user2 = User.new
326
+ @user2.email = 'email@example.com'
327
+ refute_equal @user1.encrypted_email_salt, @user2.encrypted_email_salt
328
+ end
329
+
330
+ def test_should_decrypt_second_record
331
+ @user1 = User.new
332
+ @user1.email = 'test@example.com'
333
+
334
+ @user2 = User.new
335
+ @user2.email = 'test@example.com'
336
+
337
+ assert_equal 'test@example.com', @user1.decrypt(:email, @user1.encrypted_email)
338
+ end
339
+ end
@@ -0,0 +1,106 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../test_helper', __FILE__)
3
+
4
+ # Test to ensure that existing representations in database do not break on
5
+ # migrating to new versions of this gem. This ensures that future versions of
6
+ # this gem will retain backwards compatibility with data generated by earlier
7
+ # versions.
8
+ class CompatibilityTest < Minitest::Test
9
+ class NonmarshallingPet < ActiveRecord::Base
10
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
11
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
12
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
13
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
14
+
15
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
16
+
17
+ attr_encrypted :nickname,
18
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY) }
19
+ attr_encrypted :birthdate,
20
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY) }
21
+ end
22
+
23
+ class MarshallingPet < ActiveRecord::Base
24
+ PET_NICKNAME_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-nickname-salt')
25
+ PET_NICKNAME_KEY = 'my-really-really-secret-pet-nickname-key'
26
+ PET_BIRTHDATE_SALT = Digest::SHA256.hexdigest('my-really-really-secret-pet-birthdate-salt')
27
+ PET_BIRTHDATE_KEY = 'my-really-really-secret-pet-birthdate-key'
28
+
29
+ self.attr_encrypted_options[:mode] = :per_attribute_iv_and_salt
30
+
31
+ attr_encrypted :nickname,
32
+ :key => proc { Encryptor.encrypt(:value => PET_NICKNAME_SALT, :key => PET_NICKNAME_KEY) },
33
+ :marshal => true
34
+ attr_encrypted :birthdate,
35
+ :key => proc { Encryptor.encrypt(:value => PET_BIRTHDATE_SALT, :key => PET_BIRTHDATE_KEY) },
36
+ :marshal => true
37
+ end
38
+
39
+ def setup
40
+ ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
41
+ create_tables
42
+ end
43
+
44
+ def test_nonmarshalling_backwards_compatibility
45
+ pet = NonmarshallingPet.create!(
46
+ :name => 'Fido',
47
+ :encrypted_nickname => 'E4lJTxFG/EfkfPg5MpnriQ==',
48
+ :encrypted_nickname_iv => 'z4Q8deE4h7f6S8NNZcbPNg==',
49
+ :encrypted_nickname_salt => 'adcd833001a873db',
50
+ :encrypted_birthdate => '6uKEAiFVdJw+N5El+U6Gow==',
51
+ :encrypted_birthdate_iv => 'zxtc1XPssL4s2HwA69nORQ==',
52
+ :encrypted_birthdate_salt => '4f879270045eaad7'
53
+ )
54
+
55
+ assert_equal 'Fido', pet.name
56
+ assert_equal 'Fido the Dog', pet.nickname
57
+ assert_equal '2011-07-09', pet.birthdate
58
+ end
59
+
60
+ def test_marshalling_backwards_compatibility
61
+ pet = MarshallingPet.create!(
62
+ :name => 'Fido',
63
+ :encrypted_nickname => 'EsQScJYkPw80vVGvKWkE37Px99HHpXPFjoEPTNa4rbs=',
64
+ :encrypted_nickname_iv => 'fNq1OZcGvty4KfcvGTcFSw==',
65
+ :encrypted_nickname_salt => '733b459b7d34c217',
66
+ :encrypted_birthdate => '+VUlKQGfNWkOgCwI4hv+3qlGIwh9h6cJ/ranJlaxvU+xxQdL3H3cOzTcI2rkYkdR',
67
+ :encrypted_birthdate_iv => 'Ka+zF/SwEYZKwVa24lvFfA==',
68
+ :encrypted_birthdate_salt => 'd5e892d5bbd81566'
69
+ )
70
+
71
+ assert_equal 'Fido', pet.name
72
+ assert_equal 'Mummy\'s little helper', pet.nickname
73
+
74
+ assert_equal Date.new(2011, 7, 9), pet.birthdate
75
+ end
76
+
77
+ private
78
+
79
+ def create_tables
80
+ silence_stream(STDOUT) do
81
+ ActiveRecord::Schema.define(:version => 1) do
82
+ create_table :nonmarshalling_pets do |t|
83
+ t.string :name
84
+ t.string :encrypted_nickname
85
+ t.string :encrypted_nickname_iv
86
+ t.string :encrypted_nickname_salt
87
+ t.string :encrypted_birthdate
88
+ t.string :encrypted_birthdate_iv
89
+ t.string :encrypted_birthdate_salt
90
+ end
91
+ create_table :marshalling_pets do |t|
92
+ t.string :name
93
+ t.string :encrypted_nickname
94
+ t.string :encrypted_nickname_iv
95
+ t.string :encrypted_nickname_salt
96
+ t.string :encrypted_birthdate
97
+ t.string :encrypted_birthdate_iv
98
+ t.string :encrypted_birthdate_salt
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
106
+
@@ -0,0 +1,94 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../test_helper', __FILE__)
3
+
4
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => ':memory:'
5
+
6
+ def create_people_table
7
+ silence_stream(STDOUT) do
8
+ ActiveRecord::Schema.define(:version => 1) do
9
+ create_table :legacy_people do |t|
10
+ t.string :encrypted_email
11
+ t.string :password
12
+ t.string :encrypted_credentials
13
+ t.string :salt
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ # The table needs to exist before defining the class
20
+ create_people_table
21
+
22
+ ActiveRecord::MissingAttributeError = ActiveModel::MissingAttributeError unless defined?(ActiveRecord::MissingAttributeError)
23
+
24
+ class LegacyPerson < ActiveRecord::Base
25
+ attr_encrypted :email, :key => 'a secret key'
26
+ attr_encrypted :credentials, :key => Proc.new { |user| Encryptor.encrypt(:value => user.salt, :key => 'some private key') }, :marshal => true
27
+
28
+ ActiveSupport::Deprecation.silenced = true
29
+ def after_initialize; end
30
+ ActiveSupport::Deprecation.silenced = false
31
+
32
+ after_initialize :initialize_salt_and_credentials
33
+
34
+ protected
35
+
36
+ def initialize_salt_and_credentials
37
+ self.salt ||= Digest::SHA256.hexdigest((Time.now.to_i * rand(5)).to_s)
38
+ self.credentials ||= { :username => 'example', :password => 'test' }
39
+ rescue ActiveRecord::MissingAttributeError
40
+ end
41
+ end
42
+
43
+ class LegacyPersonWithValidation < LegacyPerson
44
+ validates_presence_of :email
45
+ validates_uniqueness_of :encrypted_email
46
+ end
47
+
48
+ class LegacyActiveRecordTest < Minitest::Test
49
+
50
+ def setup
51
+ ActiveRecord::Base.connection.tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
52
+ create_people_table
53
+ end
54
+
55
+ def test_should_decrypt_with_correct_encoding
56
+ if defined?(Encoding)
57
+ @person = LegacyPerson.create :email => 'test@example.com'
58
+ assert_equal 'UTF-8', LegacyPerson.first.email.encoding.name
59
+ end
60
+ end
61
+
62
+ def test_should_encrypt_email
63
+ @person = LegacyPerson.create :email => 'test@example.com'
64
+ refute_nil @person.encrypted_email
65
+ refute_equal @person.email, @person.encrypted_email
66
+ assert_equal @person.email, LegacyPerson.first.email
67
+ end
68
+
69
+ def test_should_marshal_and_encrypt_credentials
70
+ @person = LegacyPerson.create
71
+ refute_nil @person.encrypted_credentials
72
+ refute_equal @person.credentials, @person.encrypted_credentials
73
+ assert_equal @person.credentials, LegacyPerson.first.credentials
74
+ end
75
+
76
+ def test_should_encode_by_default
77
+ assert LegacyPerson.attr_encrypted_options[:encode]
78
+ end
79
+
80
+ def test_should_validate_presence_of_email
81
+ @person = LegacyPersonWithValidation.new
82
+ assert !@person.valid?
83
+ assert !@person.errors[:email].empty? || @person.errors.on(:email)
84
+ end
85
+
86
+ def test_should_validate_uniqueness_of_email
87
+ @person = LegacyPersonWithValidation.new :email => 'test@example.com'
88
+ assert @person.save
89
+ @person2 = LegacyPersonWithValidation.new :email => @person.email
90
+ assert !@person2.valid?
91
+ assert !@person2.errors[:encrypted_email].empty? || @person2.errors.on(:encrypted_email)
92
+ end
93
+
94
+ end