From 7c6b6ff80c3800563a86e3d1d9839a584b708ce1 Mon Sep 17 00:00:00 2001 From: nightpool Date: Thu, 21 Jul 2022 11:47:39 -0500 Subject: [PATCH 1/2] Only include instance methods once attr_encrypted is specified Use the "InstanceMethods" module pattern to isolate the instance methods for attr_encrypted so that they don't infect other ActiveRecord models in the codebase. This resolves some compatibility issues with other libraries that override method_missing --- lib/attr_encrypted/adapters/active_record.rb | 69 ++++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index fca9343e..1d6d3219 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -4,53 +4,50 @@ module AttrEncrypted module Adapters module ActiveRecord - def self.extended(base) # :nodoc: - base.class_eval do - - # https://github.com/attr-encrypted/attr_encrypted/issues/68 - alias_method :reload_without_attr_encrypted, :reload - def reload(*args, &block) - result = reload_without_attr_encrypted(*args, &block) - self.class.encrypted_attributes.keys.each do |attribute_name| - instance_variable_set("@#{attribute_name}", nil) + protected + # attr_encrypted method + def attr_encrypted(*attrs) + self.class_eval do + # https://github.com/attr-encrypted/attr_encrypted/issues/68 + alias_method :reload_without_attr_encrypted, :reload + def reload(*args, &block) + result = reload_without_attr_encrypted(*args, &block) + self.class.encrypted_attributes.keys.each do |attribute_name| + instance_variable_set("@#{attribute_name}", nil) + end + result end - result - end - attr_encrypted_options[:encode] = true + attr_encrypted_options[:encode] = true - class << self - alias_method :method_missing_without_attr_encrypted, :method_missing - alias_method :method_missing, :method_missing_with_attr_encrypted - end + class << self + alias_method :method_missing_without_attr_encrypted, :method_missing + alias_method :method_missing, :method_missing_with_attr_encrypted + end - def perform_attribute_assignment(method, new_attributes, *args) - return if new_attributes.blank? + def perform_attribute_assignment(method, new_attributes, *args) + return if new_attributes.blank? - send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args - send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args - end - private :perform_attribute_assignment + send method, new_attributes.reject { |k, _| self.class.encrypted_attributes.key?(k.to_sym) }, *args + send method, new_attributes.reject { |k, _| !self.class.encrypted_attributes.key?(k.to_sym) }, *args + end + private :perform_attribute_assignment - if ::ActiveRecord::VERSION::STRING > "3.1" - alias_method :assign_attributes_without_attr_encrypted, :assign_attributes - def assign_attributes(*args) - perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args + if ::ActiveRecord::VERSION::STRING > "3.1" + alias_method :assign_attributes_without_attr_encrypted, :assign_attributes + def assign_attributes(*args) + perform_attribute_assignment :assign_attributes_without_attr_encrypted, *args + end end - end - alias_method :attributes_without_attr_encrypted=, :attributes= - def attributes=(*args) - perform_attribute_assignment :attributes_without_attr_encrypted=, *args + alias_method :attributes_without_attr_encrypted=, :attributes= + def attributes=(*args) + perform_attribute_assignment :attributes_without_attr_encrypted=, *args + end end - end - end - protected - - # attr_encrypted method - def attr_encrypted(*attrs) super + options = attrs.extract_options! attr = attrs.pop attribute attr if ::ActiveRecord::VERSION::STRING >= "5.1.0" From 84713fb3cfbf06d80a98340b85cf48c53736e92b Mon Sep 17 00:00:00 2001 From: nightpool Date: Fri, 22 Jul 2022 11:13:49 -0500 Subject: [PATCH 2/2] use on_load for rails 3 and to_prepare for rails 2 --- lib/attr_encrypted/adapters/active_record.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/attr_encrypted/adapters/active_record.rb b/lib/attr_encrypted/adapters/active_record.rb index 1d6d3219..81051c49 100644 --- a/lib/attr_encrypted/adapters/active_record.rb +++ b/lib/attr_encrypted/adapters/active_record.rb @@ -133,8 +133,17 @@ def method_missing_with_attr_encrypted(method, *args, &block) end end - ActiveSupport.on_load(:active_record) do - extend AttrEncrypted - extend AttrEncrypted::Adapters::ActiveRecord + if defined?(ActiveSupport.on_load) + ActiveSupport.on_load(:active_record) do + extend AttrEncrypted + extend AttrEncrypted::Adapters::ActiveRecord + end + else + Rails.configuration.to_prepare do + ActiveRecord::Base.class_eval do + extend AttrEncrypted + extend AttrEncrypted::Adapters::ActiveRecord + end + end end end