Gem 中的配置块

use*_*745 4 ruby gem

我正在尝试编写我的第一个 gem,但对典型配置块的工作方式有点困惑。为了说明,我想要的是能够写出类似的东西

MyGem.configure do |c|
    c.property1 = 1
    c.property2 = 'some string'
end
Run Code Online (Sandbox Code Playgroud)

我的 ruby​​ 知识不够深入,所以虽然我很高兴使用块,但我不确定如何编写需要块的代码。

如何以这种方式编写要配置的“MyGem”类(大概是通过实例变量)?

Jos*_*eek 5

这将是实现您的示例的可能方法:

class MyGem
  Config = Struct.new :property1, :property2  # => MyGem::Config

  def self.configure(&config_block)
    config_block.call config         # => "some string"
  end                                # => :configure

  def self.config
    @config ||= Config.new  # => #<struct MyGem::Config property1=nil, property2=nil>, #<struct MyGem::Config property1=1, property2="some string">
  end                       # => :config
end                         # => :config

MyGem.configure do |c|         # => MyGem
  c.property1 = 1              # => 1
  c.property2 = 'some string'  # => "some string"
end                            # => "some string"

MyGem.config  # => #<struct MyGem::Config property1=1, property2="some string">
Run Code Online (Sandbox Code Playgroud)

但我也提倡在实例而不是类上存储状态:

class MyGem
  Config = Struct.new :property1, :property2  # => MyGem::Config
  def initialize(&config_block)
    config_block.call config                  # => "some string"
  end                                         # => :initialize

  def config
    @config ||= Config.new  # => #<struct MyGem::Config property1=nil, property2=nil>, #<struct MyGem::Config property1=1, property2="some string">
  end                       # => :config
end                         # => :config

instance = MyGem.new do |c|    # => MyGem
  c.property1 = 1              # => 1
  c.property2 = 'some string'  # => "some string"
end                            # => #<MyGem:0x007fc1691ecb20 @config=#<struct MyGem::Config property1=1, property2="some string">>

instance.config  # => #<struct MyGem::Config property1=1, property2="some string">
Run Code Online (Sandbox Code Playgroud)

如果你这样做,你就没有全局状态。请注意,我们可以有多种不同的配置(例如,每个客户端都有自己的配置,或者您想要编写多个测试,但现在每个都有可能破坏其他配置)。我写了一篇关于实现单例模式的许多方法的博客,以及为什么你不应该这样做:http : //blog.8thlight.com/josh-cheek/2012/10/20/implementing-and -testing-the-singleton-pattern-in-ruby.html