ruby-on-rails - rails 5 : read-only enum attribute

标签 ruby-on-rails enums ruby-on-rails-5

我有一个模块,由多个带有 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/

相关文章:

JavaScript 无法使用 Safari 加载到生产网站上

java - Java 枚举中重写的抽象方法中的代码问题

ruby-on-rails - 如何访问 Rails 5 Action Cable Channels 中的关注点和应用程序 Controller 代码

ruby-on-rails - Rails 5.2 什么时候结束?

javascript - 如何使用 javascript 从 ruby​​ on rails 获取数据

ruby-on-rails - 使用 Barby gem 打印 - 条码图像模糊

ruby-on-rails - Ruby on Rails 模块包含模块

ruby-on-rails - ActionMailer 不发送在 Fake_sqs 中排队的电子邮件

java - 你能解释一下这个使用枚举的java程序的输出吗?

c++ - 是否有任何理由在 C++ 中使用枚举来代替已有的 boolean 值?