Ruby Альтернатива использованию переменных класса в ActiveSupport::Concern

У меня есть приложение, которое требует использования шифрования для некоторых полей в базе данных. В настоящее время это реализуется с помощью задачи, которая обрабатывает тонкие детали шифрования и управления полями во включенных классах. Важно, чтобы система могла программно определять, какие классы включают эту проблему, но даже более конкретно программно должен быть хороший способ определить, какие поля зашифрованы.

Сегодня это реализовано, работает, используя переменные класса, как это:

module EncryptedFields

    extend ActiveSupport::Concern

    included do
        @@encrypted_attributes ||= {}
        @@encrypted_attributes[self.to_s] ||= []

        def self.encrypted attribute, options={}

            @@encrypted_attributes[self.to_s] << attribute

            ### Other stuff
        end
    end
end

Входит в класс, как это:

class SomeEcryptedModel

   include EncryptedFields

   encrypted :field_name, options
   encrypted :other_field_name, options

   #etc
end

Переменная класса @@encrypted_attributes будет правильно захватывать хэш пар ключ-значение с включенным именем класса в качестве ключа и массивом зашифрованных атрибутов в качестве значения. Я рассмотрел возможность использования системы регистрации для зашифрованных моделей, чтобы использовать и "регистрировать" себя и свои атрибуты, но с этим связано гораздо больше накладных расходов, и я хотел бы начать с чего-то более простого, если это не слишком небезопасно.,

Это на самом деле работает нормально в моем текущем приложении, но у меня нет большого опыта работы с проблемами или переменными класса, поэтому я обеспокоен тем, допустил ли я серьезный просчет того, как это будет вести себя. Где здесь ошибки? Я начал программировать с тех пор, как начал работать с ruby ​​(не так давно), что в общем случае переменные класса следует избегать.

Я уже однажды был укушен этим, потому что изначально я думал, что переменная класса @@encrypted_attributes будет переменной класса во включенном классе; это, видимо, было не так. Каждая новая модель, которая включала его, перезаписывала его, поэтому я пришел к выводу, что эта переменная класса, очевидно, относится к самой проблеме. По крайней мере, такое поведение я наблюдаю. В итоге это оказалось более желательным поведением, потому что теперь я могу получить полный список зашифрованных моделей. Это имеет очевидное ограничение: он может возвращать только список зашифрованных моделей и атрибутов для моделей, которые были загружены.

Итак, мой вопрос:

Это правильный вариант использования для переменных класса или есть альтернативный (лучший?) Способ сбора этой же информации? Если это приемлемый вариант использования переменной класса, какие некоторые подводные камни и / или средства защиты я должен добавить, чтобы код работал так, как я намеревался?

Может быть, я просто пытаюсь быть слишком умным, и я должен просто написать свой список? Спасибо за помощь!

1 ответ

Решение

Вы можете пойти по этому пути альтернативно, чтобы коснуться подхода:

module EncryptedFields
  @encrypted_attributes ||= {}

  def self.included(klass)
    @encrypted_attributes[klass.name] ||= []
    klass.extend(ClassMethods)
  end

  def self.add(class_name, attribute)
    @encrypted_attributes[class_name] << attribute
  end

  module ClassMethods
    def encrypted(attribute, options={})
      EncryptedFields.add(name, attribute)
      # Other stuff
    end
  end
end

class Stuff
  include EncryptedFields

  encrypted :ololo
  encrypted :new_name
end

EncryptedFields.instance_variable_get(:@encrypted_attributes)
=> {"Stuff"=>[:ololo, :new_name]}

Вам не нужны переменные класса здесь. Переменной экземпляра модуля будет достаточно. У вас нет наследства, и вы не можете создать экземпляр модуля, поэтому у вас всегда будет только одно место, где @encripted_attributes переменная будет определена, и это будет вашим EncriptedFields модуль.

Хорошая статья о разнице между переменными класса и переменными экземпляра класса: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

Другие вопросы по тегам