Аксессуар хранилища для вложенного JSON

У меня есть модель "Организация", в которой хранится вся информация, связанная с организацией. Существует поле типа JSONB с именем «интеграции», в котором хранится информация, относящаяся ко всем внешним интеграциям служб, которые есть в организации.

Как использовать методы доступа к хранилищу для доступа к информации, хранящейся во вложенном JSON, например:

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

Я знаю, что могу получить доступ к mailchimp с помощью доступа к хранилищу следующим образом:

store_accessor :integrations, :mailchimp

Как я могу легко получить доступ к api_key mailchimp?


person Michael Victor    schedule 07.06.2015    source источник


Ответы (2)


Вы правы, к сожалению, store_accessor не позволяет вам получить доступ к вложенным ключам. Причина в том, что store_accessor — это просто ярлык, который определяет методы получения и установки:

# 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. Чтобы реализовать собственный набор методов получения и установки вручную:

    # 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, который бы динамически определял одни и те же методы установки и получения для набора атрибутов, которые вы передаете. Вам нужно взять базовую реализацию Rails store_accessor и добавить к ней дополнительную итерацию хеш-ключей. . Не уверен, что это будет легко, но определенно было бы интересно увидеть, как они делятся как жемчужина.

  3. Оставьте сами Rails и используйте мощь поддержки типа postgres json с чистым кодом SQL. Например, вы можете получить доступ к атрибуту api_key примерно так:

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

    Дополнительные сведения о запросах postgres json можно найти здесь.

person twonegatives    schedule 07.06.2015

Я искал то же самое. Как указал @twonegatives, store_accessor нам не поможет. Но я обнаружил, что метод #dig очень хорошо работает для получения данных. Так...

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

def username
  integrations.dig("sendgrid", "username")
end
person spflow    schedule 27.06.2019