使用块配置类

时间:2016-01-12 09:08:04

标签: ruby

我有一个基本模块,里面有一些逻辑,它包含在各种类中。现在我需要一个configure块来设置类的行为方式。

我尝试了以下代码:

class MyConfig
  attr_accessor :foo, :bar
end

module BaseModule
  def self.included base
    base.include InstanceMethods
    base.extend ClassMethods
  end

  module ClassMethods
    attr_reader :config

    def configure &block
      @config = MyConfig.new
      block.call(@config)
    end
  end

  module InstanceMethods
    def do_something
      puts self.class.config.inspect
    end
  end
end

class MyClass1
  include BaseModule

  configure do |config|
    config.foo = "foo"
  end
end

class MyClass2
  include BaseModule

  configure do |config|
    config.bar = "bar"
  end
end

MyClass1.new.do_something
#<MyConfig:0x007fa052877ea0 @foo="foo">
MyClass2.new.do_something
#<MyConfig:0x007fa052877ce8 @bar="bar">
  
      
  1. 我不确定模块/类的实例变量@config是否是配置类的最佳方法。这是正确的方法,还是有更好的解决方案?
  2.   
  3. 当模块仅包含在base.extend ClassMethods中时,是否也可以使用include BaseModule?开发人员可以期望只包含实例方法,但作为副作用,还有扩展的类方法。
  4.   

更新

我添加了一个MyConfig类,从中创建了一个新实例。这样做的好处是可以使用config.foo = "foo"

1 个答案:

答案 0 :(得分:0)

我已经改变了你的代码,使用了我和很多流行的宝石(比如设计)用于配置的方法。希望你会喜欢它:))

module BaseModule
  def self.included base
    base.include InstanceMethods
    base.extend ClassMethods
  end

  module ClassMethods
    mattr_accessor :foo
    @@foo = 'initial value'

    def configure &block
      block.call(self)
    end
  end

  module InstanceMethods
    def do_something
      puts foo
    end
  end
end

class MyClass1
  include BaseModule

  configure do |klass|
    klass.foo = "foo"
  end
end

class MyClass2
  include BaseModule

  configure do |klass|
    klass.foo = "bar"
  end
end

MyClass1.new.do_something
# => "foo"
MyClass2.new.do_something
# => "bar"

变化是:

  1. 使用mattr_accessor - 它会为您的方法创建getter和setter,如果您愿意,可以选择退出其中一些,更多信息here
  2. configure方法返回self,这样您就可以用简单,可读,类似于rails的方式配置您的类
  3. 示例:

    Kid.config do |k|
      k.be_kind = false
      k.munch_loudly = true
      k.age = 12
    end