24

我有存储与组织相关的所有信息的模型“组织”。有一个名为“integrations”的 JSONB 类型字段,用于存储与组织拥有的所有外部服务集成相关的信息。

如何使用存储访问器访问存储在嵌套 JSON 中的信息,例如:

{
 "mailchimp": {"api_key":"vsvsvef", "list_id":"12345"},
 "sendgrid" : {"username":"msdvsv", "password":"123456"}
}

我知道我可以使用这样的商店访问器访问 mailchimp:

store_accessor :integrations, :mailchimp

如何轻松访问 mailchimp 的 api_key?

4

3 回答 3

28

你是对的,不幸的store_accessor是不允许你访问嵌套键。原因是这store_accessor基本上只是定义 getter 和 setter 方法的快捷方式:

# here is a part of store_accessor method code, you can take a look at
# full implementation at
# http://apidock.com/rails/ActiveRecord/Store/ClassMethods/store_accessor
_store_accessors_module.module_eval do
  keys.each do |key|
    # here we define a setter for each passed key
    define_method("#{key}=") do |value|
      write_store_attribute(store_attribute, key, value)
    end

    # and here goes the getter
    define_method(key) do
      read_store_attribute(store_attribute, key)
    end
  end
end

因此,您的选择是:

  1. 要手动实现您自己的一组 getter 和 setter 方法:

    # somewhere in your model
    def mailchimp_api_key
      self.mailchimp["api_key"]
    end
    
    def mailchimp_api_key= value
      self.mailchimp["api_key"] = value
    end
    

    这解决了一个问题,但是您必须为每个嵌套属性重复编写很多这样的内容。

  2. 要在模块内编写您自己的辅助方法,ActiveRecord::Store::ClassMethods该方法将为您传入的一组属性动态定义相同的 setter 和 getter 方法。您必须采用 Rails 的基本实现store_accessor并向其添加额外的哈希键迭代。不确定这是否会是一件容易的事,但看到作为宝石分享肯定会很有趣。

  3. 离开 Rails 本身并通过一些纯代码使用 postgresjson类型支持的强大功能。SQL例如,您可以使用以下方式访问api_key属性:

    SELECT integrations->'mailchimp'->>'api_key' as mailchimp_api_key FROM your_table_name;
    

    更多关于 postgres json 查询的信息可以在这里找到。

于 2015-06-07T15:16:47.920 回答
4

您可以使用属性 API执行此操作

store_accessor :integrations, :mailchimp
store_accessor :mailchimp, :api_key, :list_id
attribute :mailchimp, :json # :jsonb also works if you're using a PG column of that type for `integrations`
于 2021-09-10T06:54:53.863 回答
3

我一直在寻找同样的东西。正如@twonegatives 所指出的, store_accessor 不会帮助我们。但我确实发现#dig 方法对于获取数据非常有效。所以...

#somewhere in Organization model
def api_key
  integrations.dig("mailchimp", "api_key")
end

def username
  integrations.dig("sendgrid", "username")
end
于 2019-06-27T18:04:43.990 回答