Module: Tins::DSLAccessor

Included in:
Module
Defined in:
lib/tins/dslkit.rb

Overview

The DSLAccessor module contains some methods, that can be used to make simple accessors for a DSL.

class CoffeeMaker
  extend Tins::Constant

  constant :on
  constant :off

  extend Tins::DSLAccessor

  dsl_accessor(:state) { off } # Note: the off constant from above is used

  dsl_accessor :allowed_states, :on, :off

  def process
    allowed_states.include?(state) or fail "Explode!!!"
    if state == on
      puts "Make coffee."
    else
      puts "Idle..."
    end
  end
end

cm = CoffeeMaker.new
cm.instance_eval do
  state      # => :off
  state on
  state      # => :on
  process    # => outputs "Make coffee."
end

Note that Tins::SymbolMaker is an alternative for Tins::Constant in this example. On the other hand SymbolMaker can make debugging more difficult.

Instance Method Summary collapse

Instance Method Details

#dsl_accessor(name, *default, &block) ⇒ Object

This method creates a dsl accessor named name. If nothing else is given as argument it defaults to nil. If *default is given as a single value it is used as a default value, if more than one value is given the default array is used as the default value. If no default value but a block block is given as an argument, the block is executed everytime the accessor is read in the context of the current instance.

After setting up the accessor, the set or default value can be retrieved by calling the method name. To set a value one can call name :foo to set the attribute value to :foo or name(:foo, :bar) to set it to [ :foo, :bar ].



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/tins/dslkit.rb', line 392

def dsl_accessor(name, *default, &block)
  variable = "@#{name}"
  define_method(name) do |*args|
    if args.empty?
      result =
        if instance_variable_defined?(variable)
          instance_variable_get(variable)
        end
      if result.nil?
        result = if default.empty?
          block && instance_eval(&block)
        elsif default.size == 1
          default.first
        else
          default
        end
        instance_variable_set(variable, result)
        result
      else
        result
      end
    else
      instance_variable_set(variable, args.size == 1 ? args.first : args)
    end
  end
end

#dsl_lazy_accessor(name) {|default| ... } ⇒ Symbol

The dsl_lazy_accessor method defines a lazy-loaded accessor method with a default block.

This method creates a dynamic accessor that initializes its value lazily when first accessed. It stores the default value as a block in an instance variable and evaluates it on first access. If a block is passed to the accessor, it sets the instance variable to that block for future use.

Parameters:

  • name (Object)

    the name of the accessor method to define

Yields:

  • (default)

    optional block that provides the default value for initialization

Returns:

  • (Symbol)

    returns name of the defined method.



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/tins/dslkit.rb', line 432

def dsl_lazy_accessor(name, &default)
  variable = "@#{name}"
  define_method(name) do |*args, &block|
    if !block && args.empty?
      if instance_variable_defined?(variable)
        instance_eval(&instance_variable_get(variable))
      elsif default
        instance_eval(&default)
      end
    elsif block
      instance_variable_set(variable, block)
    else
      raise ArgumentError, '&block argument is required'
    end
  end
end

#dsl_reader(name, *default, &block) ⇒ Object

This method creates a dsl reader accessor, that behaves exactly like a #dsl_accessor but can only be read not set.



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/tins/dslkit.rb', line 451

def dsl_reader(name, *default, &block)
  variable = "@#{name}"
  define_method(name) do |*args|
    if args.empty?
      result =
        if instance_variable_defined?(variable)
          instance_variable_get(variable)
        end
      if result.nil?
        if default.empty?
          block && instance_eval(&block)
        elsif default.size == 1
          default.first
        else
          default
        end
      else
        result
      end
    else
      raise ArgumentError, "wrong number of arguments (#{args.size} for 0)"
    end
  end
end