Есть ли в Ruby эквивалент method_missing для неопределенных переменных экземпляра? - PullRequest
11 голосов
/ 04 октября 2011

Когда я вызываю метод, который не существует, method_missing сообщит мне имя метода.Когда я пытаюсь получить доступ к переменной, которая не была установлена, значение просто nil.

Я пытаюсь динамически перехватить доступ к переменным экземпляра nil и вернуть значение, основанное на именипеременная доступБлижайшим эквивалентом будет PHP __get.Есть ли в Ruby эквивалентная функциональность?

Ответы [ 4 ]

2 голосов
/ 05 октября 2011

Я не верю, что это возможно в Ruby. Рекомендованным способом будет использование в ваших шаблонах метода '' user '', а не экземпляра '' @user '' var.

Это согласуется с тем, как вы обращаетесь с объектами Ruby извне (obj.user - это метод, который ссылается на @user, но на самом деле не является @user). Если вам нужна какая-либо особая логика с атрибутом, лучше всего использовать метод (или method_missing) независимо от того, обращаетесь ли вы к нему изнутри или снаружи объекта.

1 голос
/ 06 октября 2011

Смотрите мой ответ на другой похожий вопрос . Но то, что вы можете сделать это, не означает, что это хорошая идея. Разумный дизайн, как правило, позволяет преодолеть потребность в подобных вещах и позволяет создавать более читаемый и, следовательно, обслуживаемый код.

instance_variable_get кажется самым близким эквивалентом PHP __get из того, что я вижу (хотя я не пользователь PHP).

Если посмотреть на соответствующий исходный код Ruby , единственный «отсутствующий» метод для переменных - это const_missing для констант, ничего для переменных экземпляра.

0 голосов
/ 24 июня 2018

Немного поздно, но instance_variable_missing - то же самое, что и method_missing до некоторой точки ... Возьмем следующий класс:

class Test
 def method_missing(*args)
  puts args.inspect
 end
end 
t = Test.new

Теперь давайте возьмем несколько переменных экземпляра:

t.pineapples     #=> [:pineapples]
t.pineapples = 5 #=> [:pineapples=,5]

Не уверен, почему метод для вас ноль ...

РЕДАКТИРОВАТЬ:

По звукам, которые вы хотите выполнить:

t = SomeClass.new
t.property.child = 1

Итак, давайте попробуем вернуть объект Test из нашего предыдущего примера:

class Test
 def method_missing(*args)
  puts args.inspect
  return Test.new
 end
end 

Так что же происходит, когда мы вызываем:

t = Test.new
t.property.child = 1
#=>[:property]
#=>[:child=,1]

Итак, это показывает, чтоэто действительно возможно сделать.OpenStruct использует эту же технику для динамической установки переменных экземпляра.В приведенном ниже примере я создаю EternalStruct, который делает именно то, что вы хотели:

require 'ostruct'
class EternalStruct < OpenStruct
  def method_missing(*args)
    ret = super(*args)
    if !ret
      newES = EternalStruct.new
      self.__send__((args[0].to_s + "=").to_sym, newES)
      return newES
    end
  end
end

Использование EternalStruct:

t = EternalStruct.new
t.foo.bar.baz = "Store me!"
t.foo.bar.baz #=> "Store me!"
t.foo #=> #<EternalStruct bar=#<EternalStruct baz="Store me!">>
t.a = 1
t.a #=> 1
t.b #=> #<EternalStruct:...>
t.b = {}
t.b #=> {}
def t.c(arg)
  puts arg
end
t.c("hi there") #=> "hi there"
0 голосов
/ 04 октября 2011

нет instance_variable_missing (по крайней мере, я знаю об этом) Но почему вы обращаетесь к переменным экземпляра со случайным именем?

Если ваш поток весь доступ к состоянию объекта через вызовы методов (как вы должны в любом случае), то вам это не нужно.

Если вы ищете способ определить магические вещи, не путаясь с поиском метода, вы можете использовать const_missing.

...