微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

您可以根据 Rails 中的 JSONB 列建立关联吗?

如何解决您可以根据 Rails 中的 JSONB 列建立关联吗?

我有一个使用 Noticed gem 发送通知的 Rails 应用程序(rails v6.0.3,ruby 2.7.1)。我有以下模型配置:

class vendor < ApplicationRecord
    has_noticed_notifications
end

如其自述文件中所述,has_noticed_notifications 是“用于关联和销毁通知记录 where(params: {param_name.to_sym => self})”的助手

所以当我像这样创建通知时...

        vendorAddednotification.with(
          vendor: vendor,data_source: "user",).deliver(some_user) # => Notification inserted!

我希望能够使用 Noticed 方法找到引用供应商的通知,如下所示:

vendor = vendor.find ...
vendor.notifications_as_vendor # => Expected: [ Notification#123 ]

然而,输入总是一个空数组(Actual => []

我查看了 their source code,它看起来像 notifications_as_vendor 是以下查询

Notification.where(params: { :vendor => self }) # where self = an instance of the vendor model

但是,这似乎不起作用,我不确定是否应该这样做。我尝试运行一个更简单的查询,看看它是否有效......

Notification.where(params: { :data_source => "user" })

但这也不起作用。但是,当我使用不同的签名运行相同的查询时,它确实做到了:

Notification.where("params->>'data_source' = ?","user")

所以我的问题是——这是 Notified 的错误,还是我的配置中遗漏了什么?我为此使用 Psql,这是相关的架构:

...
  create_table "notifications",force: :cascade do |t|
    t.string "recipient_type",null: false
    t.bigint "recipient_id",null: false
    t.string "type",null: false
    t.jsonb "params"
    t.datetime "read_at"
    t.datetime "created_at",precision: 6,null: false
    t.datetime "updated_at",null: false
    t.index ["read_at"],name: "index_notifications_on_read_at"
    t.index ["recipient_type","recipient_id"],name: "index_notifications_on_recipient_type_and_recipient_id"
  end

...

以下是相关模型:

class vendorAddednotification < Noticed::Base
  deliver_by :database

  param :vendor
  param :data_source
end

class Notification < ApplicationRecord
  include Noticed::Model
  belongs_to :recipient,polymorphic: true
end

先谢谢你!

解决方法

我找到了它不工作的原因,这似乎是 Notified 的问题。

在我运行的纯 SQL 中:

# PLAIN SQL
select "params" from "notifications" limit 1 

返回通知的参数(返回通知的 id=77)

# PLAIN SQL Result
"{""added_by"": {""_aj_globalid"": ""gid://stack-shine/WorkspaceMember/269""},""data_source"": ""user"",""_aj_symbol_keys"": [""workspace_vendor"",""data_source"",""added_by""],""workspace_vendor"": {""_aj_globalid"": ""gid://stack-shine/WorkspaceVendor/296""}}"

现在在 Rails 中,当我这样做时

vendor = Notification.find(77).params[:vendor]
vendor.notifications_as_vendor.to_sql

结果是……

"SELECT \"notifications\".* FROM \"notifications\" WHERE \"notifications\".\"params\" = '{\"vendor\":{\"_aj_globalid\":\"gid://stack-shine/Vendor/296\"},\"_aj_symbol_keys\":[\"vendor\"]}'"

...从该查询中提取的参数是:

'{\"vendor\":{\"_aj_globalid\":\"gid://stack-shine/Vendor/296\"},\"_aj_symbol_keys\":[\"vendor\"]}'

所以...在数据库中,序列化的参数是A,但是Rails是搜索B:

# A: `params` In the database
"{""added_by"": {""_aj_globalid"": ""gid://stack-shine/WorkspaceMember/269""},""_aj_symbol_keys"": [""vendor"",""vendor"": {""_aj_globalid"": ""gid://stack-shine/Vendor/296""}}"
# B: `params` Searched with by Rails
"{\"vendor\":{\"_aj_globalid\":\"gid://stack-shine/Vendor/296\"},\"_aj_symbol_keys\":[\"vendor\"]}"

显然这个查询不能工作,因为数据库中的参数不是 Rails 搜索的参数。

数据库中的通知在 Vendor 未搜索到的“供应商”(“data_source”和“ added_by”)之上有额外的参数。这就是它什么都不返回的原因吗?

现在,我将通过将 vendor_id 存储在 params 中并执行类似 Notification.where("params >> vendor_id = ?",123)

之类的操作来自己查找通知

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。