From 8f4be41d161ef8ec181a5486b96fce725393c5f0 Mon Sep 17 00:00:00 2001 From: nate Date: Mon, 26 Apr 2010 01:09:31 -0500 Subject: [PATCH] ensures original options are reinitialized even if there is in error encrypting/decrypting --- lib/attr_encrypted.rb | 35 +++++++++++++++++++++-------------- test/attr_encrypted_test.rb | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/lib/attr_encrypted.rb b/lib/attr_encrypted.rb index b1366ba1..4dd782a4 100644 --- a/lib/attr_encrypted.rb +++ b/lib/attr_encrypted.rb @@ -1,5 +1,6 @@ require 'eigenclass' require 'encryptor' +require 'ruby-debug' module AttrEncrypted def self.extended(base) @@ -177,26 +178,32 @@ def attr_encrypted(*attrs) end define_method "#{attribute}" do - value = instance_variable_get("@#{attribute}") - encrypted_value = send(encrypted_attribute_name.to_sym) - original_options = [:key, :if, :unless].inject({}) do |hash, option| - hash[option] = options[option] - options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self - hash + begin + value = instance_variable_get("@#{attribute}") + encrypted_value = send(encrypted_attribute_name.to_sym) + original_options = [:key, :if, :unless].inject({}) do |hash, option| + hash[option] = options[option] + options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self + hash + end + value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil? + ensure + options.merge!(original_options) end - value = instance_variable_set("@#{attribute}", self.class.send("decrypt_#{attribute}".to_sym, encrypted_value)) if value.nil? && !encrypted_value.nil? - options.merge!(original_options) value end define_method "#{attribute}=" do |value| - original_options = [:key, :if, :unless].inject({}) do |hash, option| - hash[option] = options[option] - options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self - hash + begin + original_options = [:key, :if, :unless].inject({}) do |hash, option| + hash[option] = options[option] + options[option] = self.class.send :evaluate_attr_encrypted_option, options[option], self + hash + end + send("#{encrypted_attribute_name}=".to_sym, self.class.send("encrypt_#{attribute}".to_sym, value)) + ensure + options.merge!(original_options) end - send("#{encrypted_attribute_name}=".to_sym, self.class.send("encrypt_#{attribute}".to_sym, value)) - options.merge!(original_options) instance_variable_set("@#{attribute}", value) end end diff --git a/test/attr_encrypted_test.rb b/test/attr_encrypted_test.rb index f22af03c..9b4cc0cd 100644 --- a/test/attr_encrypted_test.rb +++ b/test/attr_encrypted_test.rb @@ -1,4 +1,5 @@ require File.dirname(__FILE__) + '/test_helper' +require 'mocha' class SillyEncryptor def self.silly_encrypt(options) @@ -24,13 +25,16 @@ class User attr_encrypted :with_false_if, :key => 'secret key', :if => false attr_encrypted :with_true_unless, :key => 'secret key', :unless => true attr_encrypted :with_false_unless, :key => 'secret key', :unless => false + attr_encrypted :with_if_changed, :key => 'secret key', :if => :should_encrypt attr_encryptor :aliased, :key => 'secret_key' attr_accessor :salt + attr_accessor :should_encrypt def initialize self.salt = Time.now.to_i.to_s + self.should_encrypt = true end end @@ -249,4 +253,20 @@ def test_should_work_with_aliased_attr_encryptor assert User.encrypted_attributes.include?('aliased') end + def test_should_always_reset_options + @user = User.new + @user.with_if_changed = "encrypt_stuff" + @user.stubs(:instance_variable_get).returns(nil) + @user.stubs(:instance_variable_set).raises("BadStuff") + assert_raise RuntimeError do + @user.with_if_changed + end + + @user = User.new + @user.should_encrypt = false + @user.with_if_changed = "not_encrypted_stuff" + assert_equal "not_encrypted_stuff", @user.with_if_changed + assert_equal "not_encrypted_stuff", @user.encrypted_with_if_changed + end + end \ No newline at end of file