Вот еще один альтернативный подход, который вы можете посмотреть.Это не так элегантно, как то, что вы пытаетесь сделать, используя define_method
, но, возможно, стоит посмотреть.
Добавьте новый метод lazy_attr_reader
к Class
class Class
def lazy_attr_reader(*vars)
options = vars.last.is_a?(::Hash) ? vars.pop : {}
# get the name of the method that will populate the attribute from options
# default to 'get_things'
init_method = options[:via] || 'get_things'
vars.each do |var|
class_eval("def #{var}; #{init_method} if !defined? @#{var}; @#{var}; end")
end
end
end
используйте это так:
class Test
lazy_attr_reader :name, :via => "name_loader"
def name_loader
@name = "Bob"
end
end
В действии:
irb(main):145:0> t = Test.new
=> #<Test:0x2d6291c>
irb(main):146:0> t.name
=> "Bob"