我的模型中有一个 JSON 列,默认情况下是一个空哈希。
我想检查是否存在特定密钥,如果没有,则将空哈希与默认哈希与键合并。
在我的模型中,我正在检查实用程序(水、煤气或电(是否存在,如果没有,则插入此默认哈希:
def default_config
{:config => {"features" => {"utilities" => {"water" => true, "gas" => true, "electric" => true}}}}
end
这是我检查是否存在实用程序密钥的方式:
def water
has_water? || parent.has_water?
end
这反过来又调用这些方法(都在我的模型中(:
def utility(util)
self[:config].try(:fetch, "features", nil).try(:fetch, "utilities", nil).try(:fetch, "#{util}", nil)
end
def has_water?
utility("water") == true
end
这是为了能够配置 JSON 列,无论密钥是否已经存在,我在这里尝试:
def set_water(boolean)
new_val = cleaned_boolean(boolean)
water ? nil : self[:config].deep_merge!(default_config)
self[:config]["features"]["utilities"]["water"] = new_val
end
当我测试这个时,我得到
undefined method `[]=' for nil:NilClass
尝试设置实用程序值时出错,指示我的default_config
未合并到现有的空哈希中。
reverse_merge!
是在rails
中为Hash
设置默认值的常用方法。
self[:config].reverse_merge!(default_config)
这基本上等于:
default_config.merge!(self[:config])
保持self[:config]
中的所有内容保持不变,只是合并default_config
中缺少的键值对。
还有这个三元表达式:
water ? nil : self[:config].deep_merge!(default_config)
更习惯地写成(使用Hash#reverse_merge!
(
self[:config].reverse_merge!(default_config) unless water
由于water
返回一个boolean
值,因此通常将其写为问题,例如water?
(如has_water?
(不确定water
方法是否经常使用,但我会重构为
def has_water?(include_parent=false)
utility("water") == true || (include_parent && parent.has_water?)
end
然后调用:
self[:config].reverse_merge!(default_config) unless has_water?(true)