我的应用程序需要对数据库中的某些字段使用加密。目前,这是通过一个关注点来实现的,该关注点处理加密和管理所包含类的字段的细节。重要的是,系统能够以编程方式确定哪些类包含此问题,但更具体地说,在程序上需要有一种很好的方法来确定哪些字段是加密的。
今天使用类变量实现,工作,使用
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
将是包含类的类变量;这显然不是这样。包含它的每个新模型都会覆盖它,所以我得出结论,这个类变量显然是关注本身。至少,这似乎是我见证的行为。事实证明这最终是一种更理想的行为,因为现在我可以获得加密模型的完整列表。这有明显的局限性,它只能返回已加载模型的加密模型和属性列表。
所以,我的问题:
这是类变量的正确用例,还是有另一种(更好的?)方法来捕获相同的信息?如果这是一个可接受的类变量用例,我应该添加哪些陷阱和/或保护以确保代码按照我的意图运行?
也许我只是想要太聪明而且我应该硬编码我的名单?谢谢你的帮助!
答案 0 :(得分:2)
你可以选择这种方式来关注方法:
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/