ruby-on-rails - 在保存模型之前从视图中更改用户输入
问题描述
我有一个接受小数的模型(SQLite3 开发数据库)。但是,我希望用户输入一个字符串,例如“1:15:15”(可以人工读取为 1 小时 15 分 15 秒,或者 75 分 15 秒)。在我的模型中,我有一个 before_save 调用自定义私有方法将字符串转换为数字(请注意,是否使用私有具有相同的结果):
class LogEntry < ApplicationRecord
belongs_to :user
default_scope -> { order(date: :desc) }
before_save :convert_runtime
def convert_runtime
a = self.runtime.split(':')
#debugger
self[:runtime] = a[0].to_f * 3600 + a[1].to_f * 60 + a[2].to_f
end
end
拆分给了我一个错误,所以当我插入debugger
代码并将带有拆分的行更改为 only a = self.runtime
(查看这个值实际上是什么)时,调试器会0.1e1
为“a”变量生成一个值(a 用于数组)。因此,Rails 所做的似乎是将来自用户的字符串中的第一个值(“:”之前)转换为小数,忽略字符串的其余部分,然后再保存。有没有办法在整个字符串从视图传递到模型时对其进行操作,而不需要 Rails 首先将其转换为十进制形式?我的下一个选择是更改数据库以保存字符串。我觉得这不太理想,因为如果我想将多年的条目相加,每个字符串都需要先转换为数字,所以我宁愿将时间值存储为秒,并在输入时进行转换。
我已经坚持了一段时间了。
解决方案
您可以为您的字符串表示使用瞬态访问器,以便 activerecord 的键入助手不会转换您的值。像这样的东西:
class LogEntry < ApplicationRecord
belongs_to :user
default_scope -> { order(date: :desc) }
attr_accessor :runtime_string
before_save :convert_runtime
def convert_runtime
a = runtime_string.split(':')
#debugger
self[:runtime] = a[0].to_f * 3600 + a[1].to_f * 60 + a[2].to_f
end
end
自然,您的表单必须runtime_string
立即使用
<%= f.text_field :runtime_string %>
推荐阅读
- ios - 我们可以限制 Swift 生成的接口只能在 Xcode 中从模块访问吗?
- javascript - 我如何模拟没有索引的键值对列表(角度)?
- mysql - MySQL:如何在 MySQL 表上设置行或字节大小限制?
- postman-collection-runner - 如何使用邮递员访问 API 请求正文中的外部 csv 文件的内容?
- angular - 带有 ng2-stompjs 配置的 Angular 7
- azure-devops - 通过 Azure DevOps 部署 Service Fabric 并在 Octopus 中管理环境变量
- python - TypeError:“MongoEngine”对象不可下标
- vxworks - VxWorks 控制台在哪里存储数据
- matlab - 将数字添加到 4D 矩阵中的所有负值
- node.js - 如何使用 Kuzzle 上传文件