遅延初期化する attr_reader を追加するモジュール(改良)

すっきりさせてみた。

# add lazy initialization attribute definition
module LazyInitializationAttribute
  def LazyInitializationAttribute.append_features(mod)
    super

    def mod.lazy_attr_accesser name, hook=nil, &block
      attr_writer name
      lazy_attr_reader name, hook, &block
    end

    def mod.lazy_attr_reader name, hook=nil, &block
      raise 'Hook method name or block required' unless !hook.nil? || block
      block = block_given? ? block : Proc.new do
          self.respond_to? hook.to_sym ? self.send(hook.to_sym) : nil
      end
      self.send :define_method, name.to_sym do
        var_name = "@#{name}"
        unless instance_variable_defined? var_name
          result = instance_eval &block
          unless instance_variable_defined?(var_name) or result.nil?
            instance_variable_set(var_name, result)
          end
        end
        instance_variable_get var_name
      end
    end
  end
end