更新 Rails 4 和 PostgreSQL json 列中的单个键/值对?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25416997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 01:35:26  来源:igfitidea点击:

Updating a single key/value pair in a Rails 4 and PostgreSQL json column?

ruby-on-railsjsonpostgresqlhstore

提问by Randy Burgess

I have a rather large json document that I have to store in a field for each Evaluation instance in my app. The over time, certain actions on the app will require me to change various key/value pairs in the document. The Rails 4 and PostgreSQL json data type seems ideal for this problem, but I cannot get changes to commit to the database.

我有一个相当大的 json 文档,我必须将其存储在应用程序中每个评估实例的字段中。随着时间的推移,应用程序上的某些操作将需要我更改文档中的各种键/值对。Rails 4 和 PostgreSQL json 数据类型似乎非常适合解决此问题,但我无法更改以提交到数据库。

Here's an abbreviated workflow:

这是一个简短的工作流程:

I have a json file that I import into a field for each Evaluation record:

我有一个 json 文件,我将其导入到每个评估记录的字段中:

// example.json
{ "question_1":"no" }

I create a record and import the json:

我创建一个记录并导入 json:

>> evaluation = Evaluation.create assessments: File.read("example.json")
>> evaluation.assessments = File.read("#{Rails.root}/example.json")
=> "{ \"question_1\":\"no\" }"

Calling on the assessments field seems to work fine:

调用评估领域似乎工作正常:

>> evaluation.assessments
=> {"question_1"=>"no"}

OR

>> evaluation.assessments["question_1"]
=> "no"

Example 1

示例 1

Changing the json isn't working too well. This doesn't actually commit anything:

更改 json 的效果不太好。这实际上并没有提交任何东西:

>> evaluation.assessments["question_1"] = "yes"
=> "yes"

>> evaluation.assessments["question_1"]
=> "yes"

>> evaluation.save
   (0.3ms)  BEGIN
   (0.2ms)  COMMIT
=> true

Example #2

示例#2

Replacing with a completely new object doescommit:

用一个全新的对象替换确实提交:

>> evaluation.assessments = {"question_1"=>"yes"}
=> {"question_1"=>"yes"}

>> evaluation.save
(0.3ms)  BEGIN
SQL (0.7ms)  UPDATE "evaluations" SET "assessments" = , "updated_at" =  WHERE "evaluations"."id" = 1  [["assessments", "{\"question_1\":\"yes\"}"], ["updated_at", "2014-08-21 00:52:03.581817"]]
(3.8ms)  COMMIT
=> true
  • What am I doing wrong in Example #1?
  • Why won't the database commit the change I made to the evaluation.assessmentcolumn when I call it, change the value, and call save on the instance?
  • 我在示例 #1 中做错了什么?
  • evaluation.assessment当我调用它、更改值并在实例上调用 save 时,为什么数据库不会提交我对列所做的更改?

回答by Randy Burgess

This ended up being an easy fix due to a known bug related to ActiveRecord not knowing the changed attribute is dirty:

由于与 ActiveRecord 相关的已知错误不知道更改的属性是脏的,这最终是一个简单的修复:

https://github.com/rails/rails/issues/6127

https://github.com/rails/rails/issues/6127

Here's the solution:

这是解决方案:

>> evaluation.assessments["question_1"] = "yes"
=> "yes"

>> evaluation.assessments_will_change!
>> evaluation.save
(1.1ms)  BEGIN
SQL (1.6ms)  UPDATE "evaluations" SET "assessments" = , "updated_at" =  WHERE "evaluations"."id" = 4  [["assessments", "{\"question_1\":\"yes\"}"], ["updated_at", "2014-08-21 01:59:47.331216"]]
(2.5ms)  COMMIT
=> true