Class: Module

Inherits:
Object show all
Defined in:
lib/decorator/decorator.rb,
lib/decorator/kwargsable.rb

Instance Method Summary collapse

Instance Method Details

#decoratable_original_method_addedObject



118
# File 'lib/decorator/decorator.rb', line 118

alias decoratable_original_method_added method_added

#decorator(*args, &blk) ⇒ Object

デコレータを作成するデコレータです。デコレータを作る場合は通常これをデコレータとします。example:

class Module
  decorator
  def wrap func, *args, &blk
    puts "wrapped!"
    proc { func.call *args, &blk }

デコレータの第一引数は必ずMethodです。この場合のwrapはデコレータとして使用できます。

class TestClass
  wrap
  def wrapped *args, &blk
    puts "IN!"

もしデコレータに引数を渡した場合、それはすべてデコレータに一緒に渡されます。

class TestClass
  wrap(*example_args)
  def wrapped *args, &blk
    puts "IN!"

> ↓のargsにexample_argsが渡される

def wrap func, *args, &blk
  puts "wrapped!"
  proc { func.call *args, &blk }

デコレータの戻り値がProcである場合、関数はそのProcに置き換えられます。たとえばこの場合、wrappedはwrap内のprocに置き換えられます。



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/decorator/decorator.rb', line 94

def decorator *args, &blk

    # for example,
    # class Example
    #   decorator
    #   def self.logging
    #   ...
    # 
    #   logging
    #   def a_function
    #   ...
    after = ->(_f, *_a, &_b) do # the after is called when created the self.logging
        new_method = ->(*args, &blk) do # new function replaced to the self.logging
            add_decorator _f, *args, &blk
        end

        return new_method
    end

    decorators << [after, args, blk]
    true
end

#kwargsable(func, default_args = {}, &default_blk) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/decorator/kwargsable.rb', line 9

def kwargsable func, default_args={}, &default_blk
    params = func.parameters
    params_nonblock = params.reject { |i| i[0] == :block }
    xs = params_nonblock.map { |i| i[1] }
    ->(*args, &blk) do

        if args.last.respond_to? :to_hash
            kwargs = args.pop.to_hash
        else
            kwargs = {}
        end

        args.fill nil, args.length, params_nonblock.length - args.length - 1

        default_args.each do |key, default|
            next unless xs.include? key
            i = xs.index(key)
            if args[i].nil? then args[i] = default
            end
        end

        blk = default_blk if blk.nil?

        kwargs.each do |key, arg|
            next unless xs.include? key
            kwargs.delete key
            args[xs.index(key)] = arg
        end

        func.call *args, kwargs, &blk
    end
end

#method_added(funcname) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/decorator/decorator.rb', line 120

def method_added funcname
    decoratable_original_method_added(funcname).tap do
        next if decorators.empty?
        origin = instance_method funcname
        func = origin

        until decorators.empty?
            decorators.pop.tap do |f, args, blk|
                res = f.call func, *args, &blk
                if res.respond_to? :to_proc
                    define_method funcname, &res
                    func = instance_method func.name
                elsif Method === res || UnboundMethod === res
                    define_method funcname, res
                    func = instance_method func.name
                end
            end
        end
    end
end