dch*_*cke 3 activerecord ruby-on-rails
我的 Rails 6.1.1 应用程序中的模型有一个jsonb
名为“payloads”的类型列Tweet
。我用的是商店直接访问此属性上的各个字段:
class Tweet < ApplicationRecord\n store :payload, accessors: [:lang, :text, :entities], coder: JSON\nend\n
Run Code Online (Sandbox Code Playgroud)\n(请注意,该部分coder: JSON
是将序列化从 YAML 默认值更改为 JSON \xe2\x80\x93 所必需的,否则最终会在您的jsonb
列中看到 YAML。)
当我创建新推文时,我发现 ActiveRecord 在插入过程中错误地转义了 JSON 字符串:
\nTweet.create payload: {foo: \'bar\'}\n\nTRANSACTION (0.7ms) BEGIN\n Tweet Create (2.0ms) INSERT INTO "tweets" ("payload", ...) VALUES ($1, ...) RETURNING "id" [["payload", "\\"{\\\\\\"foo\\\\\\":\\\\\\"bar\\\\\\"}\\""], ...]\n
Run Code Online (Sandbox Code Playgroud)\n我指的是部分"\\"{\\\\\\"foo\\\\\\":\\\\\\"bar\\\\\\"}\\""
。看起来已经被双重逃脱了。这会导致一种“stringception”,其中字符串中的字符串存储在列中payloads
,导致 postgres 无法使用箭头语法对字段执行任何搜索->
。Postgres 无法将此值识别为 JSON。(然而,Rails 能够在读取操作时正确反序列化该字段,这似乎是奇迹。)
另一位 SO 用户在这里说明了这个问题:https://dbfiddle.uk/gcwTQOUm
\n当我不使用时store
,我无法重现该问题:
Tweet.create payload: {foo: \'bar\'}\n TRANSACTION (0.2ms) BEGIN\n Tweet Create (1.6ms) INSERT INTO "tweets" ("payload", ...) VALUES ($1, ...) RETURNING "id" [["payload", "{\\"foo\\":\\"bar\\"}"], ...]\n
Run Code Online (Sandbox Code Playgroud)\n"{\\"foo\\":\\"bar\\"}"
是所需的字符串。
这让我相信我使用的是store
错误的。
我检查了文档:
\n\n\n注意:如果您使用结构化数据库数据类型(例如 PostgreSQL
\nhstore
/json
或 MySQL 5.7+json
),则不需要.store提供的序列化。只需使用.store_accessor来生成访问器方法。请注意,这些列使用字符串键控哈希,并且不允许使用符号进行访问。
换句话说,因为我已经使用了jsonb
-type 列,Rails 已经知道序列化哈希 \xe2\x80\x93,应用另一个序列化会导致双重转义。
因此,不要这样做:
\nstore :payload, accessors: [:lang, :text, :entities], coder: JSON\n
Run Code Online (Sandbox Code Playgroud)\n我现在这样做:
\nstore_accessor :payload, :lang, :text, :entities\n
Run Code Online (Sandbox Code Playgroud)\n它有效。
\n 归档时间: |
|
查看次数: |
226 次 |
最近记录: |