Skip to content

blindgaenger/configurable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Configurable

Little helper to configure ruby instances in a DSLish way.

Usage

See examples/*.rb for all examples described here.

Basic usage (Triangle example)

Include Configurable in your class and define some configuration attributes:


  require 'rubygems'
  require 'configurable'

  class Triangle
    include Configurable

    config_accessor :shape
    config_accessor :color
  end

Configure some instances. Each config needs a key to be accessible beside all
the other configs. Let’s name it after some important mathematics.


  Triangle.configure 'euklid' do
    shape 'isosceles'
    color 'red'
  end

  Triangle.configure 'pythagoras' do
    shape 'equilateral'
    color 'blue'
  end

Use the configured instances.


  Triangle.configs #=>  {"euclid"=>#<Triangle:0x...>, "pythagoras"=>#<Triangle:0x...>}

  Triangle.each {|name, triangle|
    puts "#{name} => #{triangle.inspect}"
  }

  Triangle['pythagoras'].shape #=> equilateral

Of course, feel free to have a look at the source code on Github. ;)

Initalize with the configured key (Website example)

In some cases the key you use in the configure method should be available in
the model as well. Of course, you could specify it again, but that’s not necessary.

Just define (or maybe you already have) a contructor which is able to receive
the specified key. It’s up to you, what you do with it.


  class Website
    include Configurable
    
    config_accessor :name
    config_accessor :url

    def initialize(key)
      @name = key
    end
  end

  Website.configure 'StackOverflow' do
    url 'http://stackoverflow.com/'
  end

  so = Website['StackOverflow']
  so.name  #=> StackOverflow
  so.url   #=> http://stackoverflow.com/

Config attributes, readers, writers and accessors (Person example)

The basic attr_* methods are available as config_*. They create the getter
and setter methods as usual. So you can still define which attributes should be
accessible from the outside world.


  class Person
    include Configurable

    config_attribute :health     # can't be given or stolen
    config_reader    :birthday   # can't change it
    config_writer    :nickname   # don't even know how they call you
    config_accessor  :friends    # may come and go
  end
  
  Person.configure 'Bertolt Brecht' do
    health   'good'
    birthday '1898-02-10'
    nickname 'Bert'
    friends  ['Hanns Eisler', 'Karl Valentin']
  end
  
  brecht = Person['Bertolt Brecht']
  
  # attribute
  brecht.health                    #=> NoMethodError
  brecht.health = 'bad'            #=> NoMethodError
  
  # reader
  brecht.birthday                  #=> 1898-02-10
  brecht.birthday = '2008-12-24'   #=> NoMethodError
  
  # writer
  brecht.nickname = 'Herr K.'      #=> 'Herr K.'
  brecht.nickname                  #=> NoMethodError
  
  # accessor
  brecht.friends                   #=> ["Hanns Eisler", "Karl Valentin"]
  brecht.friends << 'Carola Neher' #=> ["Hanns Eisler", "Karl Valentin", "Carola Neher"]  
  brecht.friends                   #=> ["Hanns Eisler", "Karl Valentin", "Carola Neher"]  

You see, all behave the exact same way as your attr_* helpers! Except for the new
config_attribute, which defines the instance variable, but does not share it to
the outside world.

Use in configuration files (Computer example)

Please see examples/computers.rb for the working example.

Ok, at first define the model. Please note, that type is the second parameter
of the constructor.


  class Computer
    include Configurable

    config_accessor :host    
    config_accessor :type
    config_accessor :ip  
    
    def initialize(host, type)
      @host = host
      @type = type
    end
  end

Now define some DSLish config helpers. Each injects a different type as
arguments to the configure methods. Use as much arguments as you like. But it’s
important, that the key (in this case the name) is still the first argument.


  def server(name, &block)
    Computer.configure(name, :server, &block)
  end

  def notebook(name, &block)
    Computer.configure(name, :notebook, &block)
  end

Create a config file and use the DSL. Although the helpers simply wrap the
configure method it looks much nicer!


  server 'raumstation' do
    ip '192.168.0.201'
  end

  server 'wohnserver' do
    ip '192.168.0.202'
  end

  notebook 'gartenstuhl' do
    ip '192.168.0.203'
  end

Back in your ruby file, load the config and use it as usual.


  config_file = 'computers.config'
  load config_file

  ips = Computer.map {|name, computer| computer.ip }
  #=> ["192.168.0.201", "192.168.0.200", "192.168.0.202", "192.168.0.203"]

  raumstation = Computer['raumstation']
  raumstation.type #=> :server

Configs with code blocks (Tower example)

By providing a block you can define what your config_* method should do. This
way you can implement for example validations or stacks. Something like this:


class Tower
  include Configurable

  attr_reader :stack

  config_attribute :brick do |color|
    raise "argh, #{color}!!!" if color == 'purple'
    @stack ||= []
    @stack << color
  end
end

Now the brick method can be called multiple times. And for the purple color
you’ll get an angry error.


brick = Tower.configure 'nice' do
  brick 'red'
  brick 'green'
  brick 'green'
  brick 'blue'
end
brick.stack #=> ["red", "green", "green", "blue"]

That’s it!

Contact

You can contact me via mail at blindgaenger at gmail dot com, or leave me a
message on my Github profile.

About

Little helper to configure ruby instances in a DSLish way.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages