简洁的方式来获取和在轨设置JSON列键

问题描述 投票:1回答:3

我有一个JSON列模型/表中它如下

t.json :options, default: {}

该列可以在其内部含有许多按键,这样的事情

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

我想设置,轻松地获得这些值。所以,我已经做了同样的getter和setter。

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

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

但是,这只是增加了线我的代码,当添加了更多的细节它不能扩展。你可以请建议这样做的干净整洁的方式?

ruby-on-rails json ruby ruby-on-rails-4 getter-setter
3个回答
3
投票

使用动态方法创建:

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

0
投票

您只需通过键以及右侧的参数?

  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
投票

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

Writing a Module

另外,您可以编写提供上述助手作为一个模块。一个简单的模块可能是这个样子:

# 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

如果有不清楚的地方简单地要求离开的意见。

© www.soinside.com 2019 - 2024. All rights reserved.