Мне удалось выяснить это для себя!
# Unobtrusive modifications to the Class class.
class Class
# Pass a block to attr_reader and the block will be evaluated in the context of the class instance before
# the instance variable is returned.
def attr_reader(*params,&block)
if block_given?
params.each do |sym|
# Create the reader method
define_method(sym) do
# Force the block to execute before we…
self.instance_eval(&block)
# … return the instance variable
self.instance_variable_get("@#{sym}")
end
end
else # Keep the original function of attr_reader
params.each do |sym|
attr sym
end
end
end
end
Если вы добавите этот код куда-нибудь, он расширит метод attr_reader
так, что если вы сейчас сделаете следующее:
attr_reader :special_attr { p "This happens before I give you @special_attr" }
Он сработает, пока не получит @special_attr
. Он выполняется в области действия экземпляра, поэтому вы можете использовать его, например, в классах, где атрибуты загружаются из Интернета. Если вы определяете метод, такой как get_details
, который выполняет весь поиск и устанавливает @details_retrieved
в true
, тогда вы можете определить attr следующим образом:
attr_reader :name, :address, :blah { get_details if @details_retrieved.nil? }