Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails中获取和设置json列键的简洁方法_Ruby On Rails_Json_Ruby_Ruby On Rails 4_Getter Setter - Fatal编程技术网

Ruby on rails 在Rails中获取和设置json列键的简洁方法

Ruby on rails 在Rails中获取和设置json列键的简洁方法,ruby-on-rails,json,ruby,ruby-on-rails-4,getter-setter,Ruby On Rails,Json,Ruby,Ruby On Rails 4,Getter Setter,我有一个模型/表,其中有一个json列,如下所示 t.json :options, default: {} 列中可以包含许多键,如下所示 options = {"details" : {key1: "Value1", key2: "Value2"}} 我想轻松设置和获取这些值。所以我做了相同的接球手和二传手 def key1 options['details']&.[]('key1') end def key1=(value) options['details'] ||=

我有一个模型/表,其中有一个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

但这只会在我的代码中添加行,当添加更多细节时,它不会扩展。您能推荐一种干净整洁的方法吗?

使用动态方法创建:

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

您也可以将键作为参数传递,对吗

  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
简略 根据可重用性,您可以选择不同的选项。简短的选择是简单地定义方法,结合使用循环和

现在,您可以使用这些帮助程序简单地扩展类,并轻松添加读者/作者

class SomeModel < ApplicationRecord
  extend OptionDetailsAttributeAccessors

  option_details_attr_accessor :key1, :key2
end
class SomeModel

如果有什么不清楚的地方,只需在评论中提问。

这如何回答有关创建getter和setter的问题?
define_方法“#{key}=”,value do
应该是
define_方法“#{key}=”do|value |
否则答案不错。或者,
->({{{}}
可以替换为
proc{}}
,使答案不那么神秘,但这只是个人品味的问题。我还意识到,您不能在类上下文中访问
选项,只能在实例上下文中访问。这意味着此行将导致错误:
options['details'].default_proc=->(u,u{}}
@JohanWentholt感谢
do | value |
,当然,已更新。对于其他人:我从未承诺免费编写代码。我只是展示了有效的解决方案。在哪里放置初始化(初始值设定项?)取决于操作。
选项['details']&.[]('key1')
使用安全运算符的巧妙方法@Tom聪明的方法是使用
Hash#default_proc
:)@AlekseiMatiushkin是的,这是一种方法。使用长格式的
Hash#[]
可以使用安全操作符,这表明对Ruby有很好的理解。我想指出这是一个通常不会想到的巧妙的小把戏。
# 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