Canfig
Dead simple canned configuration for gems or whatever. It allows users of your gems (or whatever) to configure behavior using a familiar syntax (maybe in a rails config initializer, for example).
MyGem.configure do |config|
config.foo = 'bar'
config.enable_thingy!
endGetting Started
Add the gem to your Gemfile:
gem 'canfig'
Then run bundle install.
Or if you want to use canfig to configure one of your gems, add it as a dependency to your gemspec and require 'canfig' somewhere in your gem.
Usage
You can create a new configuration object by passing in a list of allowed options and/or a hash with defaults.
conf = Canfig::Config.new(:foo, :bar) # new config with nil values for provided keys
conf = Canfig::Config.new(foo: 'abc', bar: 123) # new config with default values
conf = Canfig::Config.new(:foo, :bar, baz: 123) # combination of the twoThen you can use that object to allow further configuration of the allowed option keys with a hash or block.
conf = Canfig.new(:foo, :bar, :baz) # shortcut for Canfig::Config.new
conf.configure(foo: 'abc', bar: 123) # with a hash
conf.configure do |config| # with a block
config.bar = 123
config.baz = Struct.new(:a, :b).new(1, 2)
end
conf.configure foo: 'abc' do |config| # or with both
config.bar = 123
config.baz = Struct.new(:a, :b).new(1, 2)
endOnly the option keys provided when initializing the configuration object can be accessed, and attempting to get or set any other keys will result in a NoMethodError (similar to a Struct).
If you want your configuration object to be more flexible, you can use Canfig::OpenConfig which allows dynamically setting and getting option keys (similar to an OpenStruct).
conf = Canfig.open # or Canfig::OpenConfig.new
conf.configure foo: 'abc' do |config| # you can set whatever you want
config.bar = 123
config.baz = Struct.new(:a, :b).new(1, 2)
endGetting Changes
The current state is saved everytime the options are altered, which allows you to grab a hash of changed attributes.
conf = Canfig.new(:foo, :bar, baz: 'abc')
conf.configure foo: 'abc' do |config| # or with both
config.baz = 123
end
conf.changed # {foo: [nil, 'abc'], baz: ['abc', 123]}Configuring Gems
This pattern isn't all that powerful on it's own, and you might be thinking "why wouldn't I just use a Hash or an OpenStruct?"
Canfig becomes particularly useful when you need to allow configuration of a class or module that will be used in different environments and scenarios (like a ruby gem).
module MyGem
mattr_reader :configuration
@@configuration = Canfig.new(:foo, :bar, :baz)
def self.configure(&block)
@@configuration.configure &block
end
endUsers of your gem could then configure it with MyGem.configure.
MyGem.configure do |config|
config.foo = 'abc'
config.bar = 123
endAnd you could check the configured options to control behavior within your gem.
module MyGem
class MyClass
def do_foo?
MyGem.configuration.foo == true
end
end
endQuick Mixins
Canfig also comes with some easy-to-use mixins for modules, classes and instances that provide a configuration module/class/instance variable and a configure module/class/instance method (similar to the gem example above).
module MyModule
include Canfig::Module
end
MyModule.configuration # <Canfig::OpenConfig>
MyModule.configure { |config| config.foo = 'abc' }
class MyClass
include Canfig::Class
end
MyClass.configuration # <Canfig::OpenConfig>
MyClass.configure { |config| config.foo = 'abc' }
class MyObject
include Canfig::Instance
end
object = MyObject.new
object.configuration # <Canfig::OpenConfig>
object.configure { |config| config.foo = 'abc' }Custom Configs
You can create your own custom configuration classes by extending either Canfig::Config or Canfig::OpenConfig as appropriate, and defining/overriding any additional functionality you need. One handy trick is to override initialize to set default keys/values without requiring them to be passed in every time.
class CustomConfig < Canfig::Config
def initialize(*args, &block)
# ignore the arguments that are passed in and set some custom keys and defaults
super(:foo, :bar, baz: 'abc', &block)
end
end
conf = CustomConfig.new # :foo => nil, :bar => nil, :baz => 'abc'You can also define custom helpers to set groups of configuration options (or do anything else, really).
class DeveloperConfig < Canfig::OpenConfig
def enter_beast_mode!
set :headphones, :on
set :status, 'do_not_disturb'
end
end
conf = DeveloperConfig.new
conf.configure do |config|
config.enter_beast_mode!
endContributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request