Я могу добавить к ответу @amadan, что этот метод, как и другие, например const_get
, method_missing
, define_method
et c, является частью инструментов для метапрограммирования в ruby.
Например:
#const_get
Допустим, у нас есть такой модуль Foo
со списком констант: BOO
, BAR
, BAZ
module Foo
BAR = 1
BAZ = 2
BOO = 3
end
теперь нам нужно распечатать все это, мы можем сделать это динамически или вручную:
def print_dynamically
Foo.constants.each do |const|
p Foo.const_get(const)
end
end
def print_manually
p Foo::BAR
p Foo::BAZ
p Foo::BOO
end
> print_dynamically
=> 1
=> 2
=> 3
> print_manually
=> 1
=> 2
=> 3
#method_missing
Допустим, у нас есть такой класс Foo
, и мы хотим добавить дружественный отлов ошибок для NoMethodError
class Foo
def boo
puts 'boo'
end
def method_missing(method_name)
puts "sorry, method: ##{method_name} not defined."
puts "Here is a list of public methods:"
# here we take all defined public methods from class Foo except `#method_missing`
p public_methods(false).reject { |n| n == :method_missing }
end
end
> foo = Foo.new
> foo.boo
=> boo
> foo.bar
=> sorry, method: #bar not defined.
=> Here is a list of public methods:
=> [:boo]
#define_method
Допустим, нам нужно определить некоторый список простых (или нет) методов, и мы не хотим просто скопировать и вставить его:
вместо:
class Foo
def foo
puts "foo"
end
def boo
puts "boo"
end
def bar
puts "bar"
end
end
> foo.foo
=> foo
> foo.boo
=> boo
> foo.bar
=> bar
вы можете просто написать его так:
class Foo
%i[foo boo bar].each do |method_name|
define_method(method_name) { puts "#{method_name}" }
end
end
> foo.foo
=> foo
> foo.boo
=> boo
> foo.bar
=> bar
Резюме: Из приведенных ниже примеров видно, что Ruby предоставляет нам множество инструментов для динамического создания методов, их получения, получения констант и их установки.
PS Это далеко не все методы, это всего лишь несколько из них, но я думаю, этого достаточно, чтобы показать, что вы можете делать с инструментами метапрограммирования в ruby.