Удобный способ получить и установить ключи столбца json в Rails - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть модель / таблица со столбцом json следующим образом

t.json :options, default: {}

В столбце может быть много ключей, что-то вроде этого

options = {"details" : {key1: "Value1", key2: "Value2"}}

Я хочуустановить и получить эти значения легко.Поэтому я сделал геттеры и сеттеры для одного и того же.

def key1
  options['details']&.[]('key1')
end

def key1=(value)
  options['details'] ||= {}
  options['details']['key1'] ||=0 
  options['details']['key1'] += value 
end

Но это просто добавляет строки в мой код и не масштабируется при добавлении большего количества деталей.Можете ли вы предложить чистый и аккуратный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Вы можете просто передать ключ в качестве параметра, верно?

  def get_key key=:key1
   options['details']&.[](key)
  end

  def set_key= value, key=:key1
   options['details'] ||= {}
   options['details'][key] ||=0 
   options['details'][key] += value 
  end
0 голосов
/ 08 февраля 2019

Simple & Short

В зависимости от возможности повторного использования вы можете выбрать различные варианты.Короткий вариант - просто определить методы, используя цикл в комбинации с #define_method.

class SomeModel < ApplicationRecord
  option_accessors = ['key1', 'key2']

  option_accessors.map(&:to_s).each do |accessor_name|
    #                     ^ in case you provide symbols in option_accessors
    #                       this can be left out if know this is not the case

    define_method accessor_name do
      options.dig('details', accessor_name)
    end

    define_method "#{accessor_name}=" do |value|
      details = options['details'] ||= {}
      details[accessor_name] ||= 0
      details[accessor_name] += value
    end
  end
end

Написание модуля

В качестве альтернативы вы можете написать модуль, которыйпредоставить вышеперечисленное в качестве помощников.Простой модуль может выглядеть примерно так:

# app/model_helpers/option_details_attribute_accessors.rb
module OptionDetailsAttributeAccessors
  def option_details_attr_reader(*accessors)
    accessors.map(&:to_s).each do |accessor|
      define_method accessor do
        options.dig('details', accessor)
      end
    end
  end

  def option_details_attr_writer(*accessors)
    accessors.map(&:to_s).each do |accessor|
      define_method "#{accessor}=" do |value|
        details = options['details'] ||= {}
        details[accessor] ||= 0
        details[accessor] += value
      end
    end
  end

  def option_details_attr_accessor(*accessors)
    option_details_attr_reader(*accessors)
    option_details_attr_writer(*accessors)
  end
end

Теперь вы можете просто расширить свой класс с помощью этих помощников и легко добавлять читателей / писателей.

class SomeModel < ApplicationRecord
  extend OptionDetailsAttributeAccessors

  option_details_attr_accessor :key1, :key2
end

Если что-то неясно, просто спроситепрочь в комментариях.

0 голосов
/ 08 февраля 2019

Использовать динамическое создание метода:

options['details'].default_proc = ->(_,_) {{}}
ALLOWED_KEYS = %i[key1 key2 key3]

ALLOWED_KEYS.each do |key|
  define_method key do
    options['details'][key] if options['details'].key?(key)
  end
  define_method "#{key}=" do |value|
    (options['details'][key] ||= 0) += value
  end
end
...