Этот код public_send("#{k}=", v)
динамически вызывает установщик того, что хранится в переменной k
.Рассмотрим следующий пример:
class FooBarBaz
attr_accessor :foo, :bar, :baz
def set_it what, value
public_send("#{what}=", value)
end
end
Это примерно эквивалентно:
def set_it what, value
case what
when "foo" then public_send("foo=", value)
when "bar" then public_send("bar=", value)
when "baz" then public_send("baz=", value)
end
end
Это примерно эквивалентно:
def set_it what, value
case what
when "foo" then self.foo=(value)
...
end
end
Это примерно эквивалентно:
def set_it what, value
case what
when "foo" then self.foo = value
...
end
end
respond_to?
вызывается заранее, чтобы проверить, действительно ли сеттер определен для этого k
в этом случае, чтобы предотвратить что-то вроде:
FooBarBaz.new.set_it :inexisting, 42
#⇒ NoMethodError: undefined method `inexisting=' for #<FooBarBaz:0x0056247695a538>
Измененная, правильная версия класса в этом ответе:
class FooBarBaz
attr_accessor :foo, :bar, :baz
def set_it what, value
public_send("#{what}=", value) if respond_to?("#{what}=")
end
end
Не выдает исключение.
FooBarBaz.new.set_it :inexisting, 42
#⇒ nil