Рубин Метапрограммирование "Глубины" - PullRequest
0 голосов
/ 11 сентября 2018

Я начинаю изучать метапрограммирование в Ruby и (я думаю) я понимаю, как добавлять экземпляры методов и переменных, но только если они передаются по одному за раз. Например, test.new_value = true. Мне интересно, как добавить дополнительную глубину к моей команде с двумя точками test.like.this. Например:

class StackOverflow
  def initialize(name)
    @name = name
  end

  def method_missing(argument, *args)
    argument = argument.to_s

    if argument =~ /failing/
      puts 'FOUND FAILING'
      puts argument
      puts args[0]
      return
    end

    if argument =~ /this_test_is/
      puts 'FOUND THIS TEST IS'
      puts argument
      puts args[0]
      return
    end

    if argument =~ /this_works=/
      instance_variable_set("@#{argument.to_s.chop}", args[0])
      return
    else
      return instance_variable_get("@#{argument}").to_s
    end
  end
end

test = StackOverflow.new("post")
test.this_works = true
puts "IT WORKED: " + test.this_works
test.this_test_is.failing

дает мне следующий вывод:

ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

IT WORKED: true
FOUND THIS TEST IS
this_test_is

undefined method `failing' for nil:NilClass
(repl):44:in `<main>'

То, что я хочу сделать, это трактовать это как пару переменных и значений. Я хотел бы знать, как выполнить оба этих сценария:

A: Распознать this_test_is и обработать его как переменную, чтобы он сохранял строку (или символ в порядке) failing.

B: признать failing переменной, и если я вижу this_test_is, тогда установите failing в true, в отличие от false, если я найду this_test_is_not.

Заранее спасибо!

1 Ответ

0 голосов
/ 11 сентября 2018

Вам необходимо добавить некую рекурсию:

class StackOverflow
  def initialize(name)
    @name = name
  end

  def method_missing(argument, *args)
    argument = argument.to_s

    if argument =~ /failing/
      puts 'FOUND FAILING'
      puts argument
      puts args[0]
      return
    end

    if argument =~ /this_test_is/
      puts 'FOUND THIS TEST IS'
      puts argument
      puts args[0]
      return StackOverflow.new("this_test_is")
    end

    if argument =~ /this_works=/
      instance_variable_set("@#{argument.to_s.chop}", args[0])
      return
    else
      return instance_variable_get("@#{argument}").to_s
    end
  end
end

test = StackOverflow.new("post")
test.this_works = true
puts "IT WORKED: " + test.this_works
test.this_test_is.failing

печатает это:

IT WORKED: true
FOUND THIS TEST IS
this_test_is

FOUND FAILING
failing
...