ruby-on-rails - Rails - 将值附加到 JsonB 字段时的更好方法
问题描述
每当将候选记录输入/移动到新入口点时,我都在努力填充 jsonB 字段。
我目前正在使用ff。方法:
(它们可以被多次调用,并且只会将新入口点附加到 jsonB 字段 [entry])
// Method in Candidate model
def log_entry(value)
self.entry = Array(self.entry) << { val: value, timestamp: Time.now.to_i }
end
def log_entry!(value)
self.log_entry(value)
self.save
end
在每个控制器入口点调用
ca = Candidate.new(name: 'John Doe')
ca.log_entry('Point 1')
ca.save
移动到新入口点时也可以这样调用
ca = Candidate.find id
ca.log_entry!('Point 2')
调用两次后的记录是这样的log_entry
: Candidate Model
Name: 'John Doe'
Entry: [{ val: 'Point 1', timestamp: '<time>' }, { val: 'Point 2', timestamp: '<time>' }]
到目前为止,上述方法正在达到预期的效果。但是我的印象是代码太杂乱了,并且有更好的方法。
任何想法将不胜感激。
解决方案
这可能看起来/感觉很混乱,只是因为这违反了单一责任原则。您没有说明为什么要为这些对象中的每一个保留似乎是访问日志的Candidate
内容,但是当您考虑它时,不应该有Candidates
责任记录访问它的原因和时间。通过以这种方式将它们耦合在一起,每当控制器入口点的两个调用者同时发生时,您将获得一个StaleObjectError
或简单地删除一个日志条目。
另外顺便说一句,这是当前编码的,要记录条目日志,您必须手动调用单独的方法。这使得以后在Candidate.find(x)
某处添加调用的任何人都需要log_entry
在检索到Candidate
.
我建议的是两件事:
将此访问日志存储到它自己的对象中,即它是一个运行日志,以便它可以轻松地同时被多个源更新。这可以通过将
log_entry
内容存储分解为它自己的对象并Candidate
通过has_many
关系将其链接到对象来实现。创建一个新的关注点,可以混合到任何需要此访问日志记录的模型中,它会覆盖任何访问器方法,例如
find
orfind_by
,以便log_entry
在返回 found 之前插入一个新的关注点Candidate
。如果您想对此进行详细说明,您可以使用装饰器模式通过使用装饰器来修改方法的内部工作,从而允许访问日志轻松附加到任何现有方法定义。
如果您需要联轴器:
既然您需要耦合,那么我建议您仍然将逻辑分解为一个关注点,以便您可以装饰需要更新这些日志条目的适当方法。并利用乐观锁定和一些更新重试逻辑来确保数据在并发请求期间不会丢失。这将消除多个知识的笨拙,将其限制在一个地方,并消除意外数据丢失的情况。
一些粗略的代码(只是find
方法修改)如下所示:
# — Candidate Class —
def find(id, reason=“”)
super(id).tap do |candidate|
Array(candidate.log_entry) << { ... }
candidate.save
rescue ActiveRecord::StaleObjectError => ex
# do some logging here
retry
end
end
上面对find方法的修改会找到请求的对象,在上面记录日志条目,在stale object错误的情况下重试记录,并返回找到的对象。这样就不需要在 Rails 应用程序的其他任何地方重复代码。
推荐阅读
- powershell - 不覆盖字符串的环境路径
- arrays - LUA 脚本:嵌套循环仅插入最后一项
- asp.net - 从 formcollection 值中设置不同类型的对象属性值
- angular - Angular 7刷新获取网关超时
- python - Keras 创建 CNN 模型“添加的层必须是类层的实例”
- java - Java BinaryTree 平衡一棵树
- sql - UTC 日期格式
- python - 我可以使用变量制作 Python time.sleep() 吗?
- python - 如何在 Python 中的弹性搜索中搜索多个 OR 条件
- windows - Windows 10,XAMPP Apache 在 PHP 从 7.3 更新到 7.4 后无法启动