Ruby无法看到方法

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

我为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


我需要的是:将parent_hash(生产env)合并采用的_哈希(例如登台环境)并通过该命令输出合并的值: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 (NoMethodErro
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={}>}>}>
ruby hash dsl
1个回答
0
投票

您在deep_merge上将InHash定义为实例方法,因此在Configus的类级别上不可见。

[我觉得deep_merge方法实际上不需要来自InHash实例的任何数据,因此,将IMO设为类方法是合理的。更改

def deep_merge(target, source)
  # ...
end

to

def self.deep_merge(target, source)
  # ...
end

然后您可以像这样在Configus.config中调用它>>

merged_hash = InHash.deep_merge(parent_hash, adopted_hash)
© www.soinside.com 2019 - 2024. All rights reserved.