Class: NRSER::LazyAttr

Inherits:
MethodDecorators::Decorator
  • Object
show all
Defined in:
lib/nrser/meta/lazy_attr.rb

Overview

Store the result of an attribute method (no args) in an instance variable of the same name and return that value on subsequent calls.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.instance_var_name(target_method) ⇒ String

Get the instance variable name for a target method.

Parameters:

  • target_method (Method)

    The method the decorator is decorating.

Returns:

  • (String)

    The name of the instance variable, ready to be provided to ‘#instance_variable_set` (has `@` prefix).



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/nrser/meta/lazy_attr.rb', line 36

def self.instance_var_name target_method
  name = target_method.name.to_s
  
  # Allow predicate methods by chopping off the `?` character.
  # 
  # Other stupid uses like `+` or whatever will raise when
  # `#instance_variable_set` is called.
  # 
  name = name[0..-2] if name.end_with? '?'
  
  "@#{ name }"
end

Instance Method Details

#call(target_method, receiver, *args, &block) ⇒ Object

Execute the decorator.

Parameters:

  • target_method (Method)

    The decorated method, already bound to the receiver.

    The ‘method_decorators` gem calls this `orig`, but I thought `target_method` made more sense.

  • receiver (*)

    The object that will receive the call to ‘target`.

    The ‘method_decorators` gem calls this `this`, but I thought `receiver` made more sense.

    It’s just ‘target.receiver`, but the API is how it is.

  • *args (Array)

    Any arguments the decorated method was called with.

  • &block (Proc?)

    The block the decorated method was called with (if any).

Returns:

  • Whatever ‘target_method` returns.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/nrser/meta/lazy_attr.rb', line 75

def call target_method, receiver, *args, &block
  unless target_method.parameters.empty?
    raise NRSER::ArgumentError.new \
      "{NRSER::LazyAttr} can only decorate methods with 0 params",
      receiver: receiver,
      target_method: target_method
  end
  
  unless args.empty?
    raise NRSER::ArgumentError.new \
      "wrong number of arguments for", target_method,
      "(given", args.length, "expected 0)",
      receiver: receiver,
      target_method: target_method
  end
  
  unless block.nil?
    raise NRSER::ArgumentError.new \
      "wrong number of arguments (given #{ args.length }, expected 0)",
      receiver: receiver,
      target_method: target_method
  end
  
  var_name = self.class.instance_var_name target_method
  
  unless receiver.instance_variable_defined? var_name
    receiver.instance_variable_set var_name, target_method.call
  end
    
  receiver.instance_variable_get var_name
      
end