我有一个模块,由多个带有 enum
属性 verification_status
的类使用:
included(self) do
enum verification_status: { dont_verify: 0, pending: 1, in_review: 2, rejected: 3, approved: 4 }
end
我希望此属性是只读的,除非通过一种专用方法,否则无法修改它,即它应该因异常而失败或返回一些错误。这里的原因是我需要它作为另一个属性修改的结果而被修改,所以当有人在可验证对象上调用 add_verification
(这是专用方法)时,具有某些属性的 Verification
将添加到该对象的先前验证列表中,并且其状态将被设置为该对象的 verification_status
。
我知道 attr_readonly
,但这并不能真正涵盖我关心的所有情况。提前致谢!
最佳答案
标准 Rails 代码不支持只读枚举,因此请将以下内容视为一种 hack。枚举值通常可以通过两种方式设置:
- 通过直接为枚举列名称设置一个值 - 正如您所说,可以使用
attr_readonly
抑制此行为,但我想没有任何方法可以实际设置 枚举值;这就是为什么我们宁愿自己重新定义 setter 方法,并且 - 通过调用
record.enum_value!
- bang 方法是动态定义的,必须重新定义以引发错误而不是设置值。
因此,在声明 enum
后,您需要重新定义 setter 方法,如下所示:
enum verification_status: { dont_verify: 0, pending: 1, in_review: 2, rejected: 3, approved: 4 }
# redefine the enum setter
define_method("verification_status=") do |args = nil|
raise "use `add_verification` instead to modify this"
end
# redefine the bang enum setters
verification_statuses.each do |status, value|
define_method("#{status}!") do
raise "use `add_verification` instead to modify this"
end
end
然后,要实际设置枚举值,您需要使用私有(private)write_attribute
方法直接设置属性,使用数字枚举值,例如:
write_attribute(:verification_status, self.class.verification_statuses[:pending])
#=> 1
# verify that the value has been indeed set
verification_status
#=> "pending"
关于ruby-on-rails - rails 5 : read-only enum attribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43828332/