我正在构建一个Rails 3.2应用程序,我必须将Sidekiq作业封装在一个单独的模型中,只是为了维护关系并处理插入和删除。
我使用Mongoid作为我的主要ORM,我想问一下如何制作不可变的记录。
这意味着在(初始化和)创建作业之后,不会接受任何更改但是删除记录。
谢谢!
答案 0 :(得分:1)
假设您的Rails应用程序是唯一的MongoDB客户端,您可以在模型层实现不变性逻辑:
class Job
include Mongoid::Document
before_validation { false if changed? && persisted? }
end
第一次在新save
上致电create
或Job
时,数据会成功保留。当您致电save
时,对象的进一步更改将不会写入数据库。 delete
的行为不会受到影响。
为什么会这样?
如果返回false,则 before_validation
取消持久性:
如果before_validation回调的返回值可以被评估为false,则进程将被中止,Base#save将返回false。如果ActiveRecord :: Validations#save!被调用它会引发一个ActiveRecord :: RecordInvalid异常。什么都不会附加到错误对象。
方法参考
changed?返回true
persisted?返回true
答案 1 :(得分:0)
我扩展了塞巴斯蒂安的excellent answer以使行为更加清晰。
class Job
include Mongoid::Document
field :msg, type: String
validate :immutability
def immutability
if changed? && persisted?
errors[:base] << "#{self.class.name} is immutable and cannot be modified after it has been persisted"
end
end
end
这是它的工作原理:
> job = Job.create(msg: 'Hello')
=> #<Job _id: 55a7ccb76d61634e87000000, msg: "Hello">
> job.update_attributes!(msg: 'Goodbye')
Mongoid::Errors::Validations:
Problem:
Validation of Job failed.
Summary:
The following errors were found: Job is immutable and cannot be modified after it has been persisted
Resolution:
Try persisting the document with valid data or remove the validations.
from /...
> job.destroy!
=> true
这有两个主要好处:
before_validation
(Calling update_attributes! on Job resulted in a false return from a callback.
)