我正在使用ActiveModel::Dirty来跟踪表单中所做的更改。现在一切都按我的预期进行。对于诸如电话号码之类的东西,当它们以表格形式出现破折号时,我只需对其进行格式化,然后电话号码就不会出现在.changed
列表中,这是预期的行为。
但是,我遇到一个问题,在我的Profile模型中使用jsonb字段。因此,问题是ActiveModel会将JSONB字段列出为已更改,即使我对其进行了专门格式化以匹配它的外观也是如此。这不是预期的行为。仍然奇怪的是,我拥有的另一个JSONB列没有遇到这种疯狂。
我遇到麻烦的JSONB字段如下所示
store_accessor :user_details, :names, :other_field
store_accessor :bank_details, :bank_city, :bank_name
user_details
和bank_details
是jsonb列。
需要注意的一些事情:names是一个数组,other_field是一个字符串。
bank_city和bank_name是字符串。
任何人都可以对为什么:user_details专门为此问题而不是:bank_details JSON列苦恼吗?
我怀疑这可能是由于我在:user_details中使用了一个数组,并且我怀疑比较在ActiveModel源代码中的某处引发了,但是也许我错了吗?
编辑: 我发现这肯定是因为我在:names中使用了一个数组。我将其更改为字符串,并且它停止以为JSON列已更改。深入研究ActiveModel源代码,看看是否可以找到原因。
编辑#2: 由于某种原因,我认为我什么都不做就解决了问题,但我是个假人,意识到我已经删除了表单中的某些内容。因此,这个问题仍然没有为我解决。任何见识都会令人惊讶。从调查ActiveModel :: Dirty源代码中我无法弄清楚为什么会这样。我不确定在哪里看。拍手拜拜,看看是否有帮助。
编辑#3: 重覆此问题的步骤
使用JSONB列创建rails模型。 设置存储访问器,您只需要执行此操作即可。 使用验证器或格式化程序将其默认为空数组。 给您的模型提供ActiveModel :: Dirty包含。 运行rails控制台。 运行以下命令。 假设user_details是JSONB列,其存储访问器是名称。
a = Profile.user_details
a.user_details = { "names" => [{"first_name" => "", "last_name" => "" }] } # This is to replicate what it would look like in a form when a user is submitting a blank entry.
a.changed # This will show that user_details has changed which is correct
a.names = []
a.changed # This will still show that user_details has changed even though it has been set back to its initial state of an empty array. This would work if it was a string field instead of an array.
答案 0 :(得分:0)
在Rails Github上打开一个问题后,我得到了回复https://github.com/rails/rails/issues/34537#issuecomment-442265161
更改是通过json,jsonb,hstore的属性强制执行的,而我被告知要进行序列化的属性类型。源代码在这里:https://github.com/rails/rails/blob/06ab7b27ea1c1ab357085439abacdb464f6742bf/activerecord/lib/active_record/store.rb#L181
我遇到此问题的原因是我不再尝试尝试的原因,因为我正在处理的项目不会使用ActiveModel :: Dirty,也不会尝试跟踪更改的方式我正在尝试这样做。
因此,遇到此问题的任何后代都祝您好运,并随时进入github问题,并抱怨此问题不起作用。