Module: DslAccessor

Included in:
Class, Module
Defined in:
lib/dsl_accessor/stores.rb,
lib/dsl_accessor/accessor.rb

Defined Under Namespace

Modules: Stores

Instance Method Summary collapse

Instance Method Details

#dsl_accessor(*args, &block) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/dsl_accessor/accessor.rb', line 31

def dsl_accessor(*args, &block)
  opts = Optionize.new(args, :name, :default)
  name = opts.name

  if !name and !block
    raise "dsl_accessor expects at least one arg"
  end

  writer =
    case opts.writer
    when NilClass then Proc.new{|value| value}
    when Symbol   then Proc.new{|value| __send__(opts.writer, value)}
    when Proc     then opts.writer
    else raise TypeError, "DSL Error: writer should be a symbol or proc. but got `#{opts.writer.class}'"
    end
  dsl_accessor_set("#{name}_writer", writer)

  default =
    case opts.default
    when NilClass then nil
    when []       then Proc.new{[]}
    when {}       then Proc.new{{}}
    when Symbol   then Proc.new{__send__(opts.default)}
    when Proc     then opts.default
    else Proc.new{opts.default}
    end
  dsl_accessor_set("#{name}_default", default)

  meta_class = (class << self; self; end)

  if opts.instance and !is_a?(Class)
    raise ArgumentError, ":instance option is implemented in only Class"
  end

  case opts.instance
  when nil
    # nop
  when true
    delegate name, :to=>"self.class"
  when Symbol
    module_eval(<<-EOS, "(__DSL_ACCESSOR__)", 1)
      def #{ name }
        @#{opts.instance} or
          raise TypeError, "DSL Error: missing @#{opts.instance} for %s##{name}" % self.class.name
        @#{opts.instance}.respond_to?(:[]) or
          raise TypeError, "DSL Error: expected @#{opts.instance}[] is implemented (%s##{name})" % self.class.name
        @#{opts.instance}[:#{ name }] || self.class.#{ name }
      end
    EOS
  else
    raise TypeError, "DSL Error: :instance should be true or Symbol, but got `%s' class" % opts.instance.class
  end

  instance_eval <<-EOS
    def #{name}(*args)
      dsl_accessor_reader("#{name}", *args)
    end
    def #{name}=(*args)
      dsl_accessor_writer("#{name}", *args)
    end
  EOS
end

#dsl_accessor_reader(key, *args) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/dsl_accessor/accessor.rb', line 4

def dsl_accessor_reader(key, *args)
  key = key.to_s
  if args.empty?
    # getter method
    if !dsl_accessor_key?(key)
      default = dsl_accessor_get("#{key}_default")
      value   = default ? default.call : nil
      dsl_accessor_writer(key, value)
    end
    dsl_accessor_get(key)
  else
    # setter method
    dsl_accessor_writer(key, *args)
  end
end

#dsl_accessor_writer(key, *args) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/dsl_accessor/accessor.rb', line 20

def dsl_accessor_writer(key, *args)
  case args.size
  when 1
    writer = dsl_accessor_get("#{key}_writer")
    value  = writer ? writer.call(*args) : args.first
    dsl_accessor_set("#{key}", value)
  else
    raise ArgumentError, "'#{key}=' expected one argument, but got #{args.size} args"
  end
end