Just did this in my constance gem, and totally love it as a way to add configuration or options configurability to your gem:
http://stufftohelpyouout.blogspot.com/2012/09/forget-struct-and-openstruct-flexible.html
like:
module MyModule
class << self
attr_accessor :debug, :proc, :some_mapping
def configure(&block); yield; end
end
end
I’ve seen people that use OpenStruct, Struct, and I had my own way to do it before this, but this seems a lot better.
That works, but it has the following disadvantages over the method I described:
- If you use ActiveSupport::Configurable you are tied to using activesupport/Rails. Many times you want to write the Gem so that it isn’t Rails-specific and want to limit dependencies.
- I know Rails uses the “pass the config into the block thing”, but it isn’t as DRY as not typing “config.” before each parameter.
- By defining the attr_accessors, you limit the chance that a user will mistype/misspell a variable.
- The way you described allows the user to define config parameters with procs and lambdas, but the way I describe allows the user to define “config parameters” as procs, lambdas, and methods, i.e. the user can actually just define a variable as:
def some_variable_name
some really involved implementation here, even refactored into various methods, etc. in the block.
end
See more at: http://stufftohelpyouout.blogspot.com/2012/09/forget-struct-and-openstruct-flexible.html
Hope that helps.
Just as an update, I had bugs in the previous code provided and fixed with help from Jesús Gabriel y Galán and Calvin B. on the list in this post: Adding method on module class to yield and allow setting of attributes? - Ruby - Ruby-Forum
module MyModule
class << self
attr_accessor :debug, :proc_or_lambda, :some_array, :some_hash, :time def configure(&blk); class_eval(&blk); end
end
end
and can configure like:
MyModule.debug = true
MyModule.proc_or_lambda = lambda{|a,b| puts "a=#{a} b=#{b}"}
…
or
MyModule.configure do
@debug = true
@proc_or_lambda = lambda{|a,b| puts "a=#{a} b=#{b}"}
@some_array = [:foo,:bar]
@some_mapping = {:key => 'value'}
def self.time; Time.now; end
end
or
MyModule.configure do
self.debug = true
self.proc_or_lambda = lambda{|a,b| puts "a=#{a} b=#{b}"}
self.some_array = [:foo,:bar]
self.some_mapping = {:key => 'value'}
def self.time; Time.now; end
end
Posted here with more examples: