我为DSL创建了deep_merged(实际上我是从configus gem复制的),但是ruby看不到该方法,我也不明白为什么。 :/
Init.rb:
require "./configus"
require "pry"
#Binding.pry
config = Configus.config :staging, :production do
production do
key1 "value1"
key2 "value2"
group1 do
key3 "value3"
key4 "value4"
end
end
staging do
key2 "new value2"
group1 do
key4 "new value4"
end
end
end
p config.key1
Configus.rb:
class Configus
class InHash
attr_reader :inner_hash
def initialize
@inner_hash = {}
end
def method_missing(name, *args, &block)
if block_given?
context = InHash.new
context.instance_eval &block
@inner_hash[name] = context
elsif args.empty?
@inner_hash[name]
else
@inner_hash[name] = args
end
end
def deep_merge(target, source)
source.each_pair do |k, v|
tv = target[k]
target[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? deep_merge(tv, v) : v
end
target
end
end
def self.config(environment, parent = nil, &block)
in_hash = InHash.new
in_hash.instance_eval &block
keys = in_hash.inner_hash.keys
index = keys.find_index(environment)
if parent && environment
parent_hash = in_hash.inner_hash[parent]
adopted_hash = in_hash.inner_hash[environment]
merged_hash = deep_merge(parent_hash, adopted_hash)
in_hash
elsif environment == keys[index]
in_hash.inner_hash[environment]
end
end
end
我需要做的是: 通过该命令合并被采用的_hash(例如,阶段env)和parent_hash(生产环境),并通过该命令输出合并后的值: p config.key_name或p config.group1.key_name
但是我复制的deep_merge方法不起作用。 :/
P.S我试图将方法放在InHash类和Configus类中,但是self.config仍然看不到它。
我需要通过该命令输出值: p config.key_name或p config.group1.key_name
当我不为环境值正确使用父函数时:
p config.key1 #=> ["value1"]
p config.group1.key3 #=> ["value3"]
但是当我使用父函数时:
p config.key1 => nil
p config.group1.key3 => Traceback (most recent call last):
init.rb:24:in `<main>': undefined method `key3' for nil:NilClass (NoMethodError)
p config => #<Configus::InHash:0x000055cfe51410d0
@inner_hash={:production=>#<Configus::InHash:0x000055cfe5140f40
@inner_hash={:key1=>["value1"], :key2=>["value2"], :group1=>#
<Configus::InHash:0x000055cfe5140bf8 @inner_hash={:key3=>["value3"],
:key4=>["value4"]}>, :[]=>[#<Configus::InHash:0x000055cfe514bee0
@inner_hash={}>], :[]==>[#<Configus::InHash:0x000055cfe514bee0
@inner_hash={}>, nil]}>, :staging=>#<Configus::InHash:0x000055cfe5140748
@inner_hash={:key2=>["new value2"], :group1=>#
<Configus::InHash:0x000055cfe51404c8 @inner_hash={:key4=>["new value4"]}>,
:each_pair=>#<Configus::InHash:0x000055cfe514bee0 @inner_hash={}>}>}>
答案 0 :(得分:0)
您在deep_merge
上将InHash
定义为实例方法,因此在Configus
的类级别上不可见。
在我看来,deep_merge
方法实际上不需要来自InHash
实例的任何数据,因此,将IMO设为类方法是合理的。更改
def deep_merge(target, source)
# ...
end
到
def self.deep_merge(target, source)
# ...
end
然后您可以像这样在Configus.config
中调用它
merged_hash = InHash.deep_merge(parent_hash, adopted_hash)