Подтвердить что ты не робот

Переменные в именах рубиновых методов

У меня есть следующий код:

for attribute in site.device_attributes
  device.attribute
end

где я хотел бы, чтобы код заменил значение "attribute" для имени метода.

Я пробовал device."#{attribute}" и различные перестановки.

Неужели это невозможно? Я что-то пропустил?

Я рассмотрел переопределение метода_missing, но я не могу понять, как это действительно поможет мне, когда моя проблема в том, что мне нужно вызвать "неизвестный" метод.

4b9b3361

Ответ 1

Вы можете использовать метод #send для вызова метода объекта по имени метода:

object.send(:foo) # same as object.foo

Вы можете передать аргументы при вызове метода:

object.send(:foo, 1, "bar", 1.23) # same as object.foo(1, "bar", 1.23)

Итак, если у вас есть имя атрибута в переменной "attribute", вы можете прочитать атрибут объекта с помощью

object.send(attribute.to_sym)

и записать значение атрибута с помощью

object.send("#{attribute}=".to_sym, value)

В Ruby 1.8.6 #send метод может выполнять любой метод объекта независимо от его видимости (вы можете, например, вызвать частные методы). Это может быть изменено в будущих версиях Ruby, и вы не должны полагаться на него. Чтобы выполнить частные методы, используйте #instance_eval:

object.instance_eval {
  # code as block, can reference variables in current scope
}

# or

object.instance_eval <<-CODE
  # code as string, can generate any code text
CODE

Update

Вы можете использовать public_send для вызова методов в отношении правил видимости.

object.public_send :public_foo # ok
object.public_send :private_bar # exception

Ответ 2

Метод "отправить" должен делать то, что вы ищете:

object = "upcase me!"
method = "upcase"
object.send(method.to_sym) # => "UPCASE ME!"

Ответ 3

Мэтт и Максим оба правильны, но не оставляют детали, которые могут помочь вам разобраться в синтаксисе #send: в Ruby вызов метода действительно отправляет сообщение. Softies on Rails имеет относительно прямое объяснение этого.

Ответ 4

вы также можете сделать

device.instance_eval(attribute)