2

我有一个应用程序需要对数据库中的某些字段使用加密。这目前是使用一个关注点来实现的,该关注点处理包含类上的加密和管理字段的详细信息。系统能够以编程方式确定哪些类包含此问题非常重要,但更具体地说,以编程方式需要有一种确定哪些字段被加密的好方法。

今天,这是使用这样的类变量实现的,工作的:

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​​(不久前)开始使用 ruby​​ 以来,我一直在编程,通常要避免使用类变量。

我已经被这个咬过一次,因为最初我认为类变量@@encrypted_attributes将是包含类的类变量;这显然不是这样。每个包含它的新模型都会覆盖它,所以我得出的结论是这个类变量显然是关注本身。至少,这是我似乎正在目睹的行为。这最终证明是一种更理想的行为,因为现在我可以获得加密模型的完整列表。这有一个明显的限制,它只能返回已加载模型的加密模型和属性列表。

所以,我的问题:

这是类变量的正确用例,还是有另一种(更好的?)方法来捕获相同的信息?如果这是一个可接受的类变量用例,我应该添加哪些陷阱和/或保护措施以确保代码按预期工作?

也许我只是想太聪明,我应该硬编码我的列表?谢谢您的帮助!

4

1 回答 1

4

您可以选择这种方式来关注方法:

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/

于 2016-08-05T15:13:02.850 回答