Как динамически открыть метод в Ruby - PullRequest
2 голосов
/ 04 мая 2011

Я хочу динамически открыть метод и вернуть значение на основе поля ввода. Я пытаюсь спросить, что я хочу с примером здесь. Если бы я смог добиться успеха в этом примере, я бы сделал то, что я хочу.

Предположим, у меня есть класс с именем Greetings, у которого есть метод с именем greet (), который принимает сообщение в качестве аргумента.

class Greetings
   def self.greet(message)
      return "good morning" if message=="gm"
      return "evening" if message=="ge"
      return "good afternoon" if message=="ga"
   end
end

Когда я делаю Greetings.greet("ge"), я получаю "вечер" в качестве вывода. Я хочу изменить это поведение, не изменяя вышеупомянутый класс Greetings (очевидная причина в том, что это внешняя библиотека).

Мой вопрос здесь прост. Что я должен делать, когда говорят, что я называю Greetings.greet("ge"), должен возвращать мне «Очень хороший вечер», а для всех других входных данных он должен возвращать то, что возвращает исходный класс. Я знаю кое-что о динамическом открытии класса в Ruby, но как бы я делегировал метод родительскому для других случаев?

И я бы написал это в папке config / initializers, так как я использую Rails.

Ответы [ 4 ]

7 голосов
/ 04 мая 2011

Псевдоним метода

Вы можете использовать псевдоним вашего старого метода, например, old_greet, и переопределить его своим собственным:

class Greetings
  class << self
    alias_method :old_greet, :greet

    def greet(message)
      (message == "ge") ? "A Very Good Evening" : old_greet(message)
    end
  end
end

, а затем вы можете:

puts Greetings.greet("ge")

Метод цепочки

С помощью Rails alias_method_chain функция:

class Greetings
  class << self
    def greet_with_modifications(message)
      (message == "ge") ? "A Very Good Evening" : greet_without_modifications(message)
    end

    alias_method_chain :greet, :modifications
  end
end

и затем вы можете:

puts Greetings.greet("ge")

Расширение класса

Вы можете создать свой собственный класс, который расширяет оригинал следующим образом:

module My
  class Greetings < ::Greetings
    def self.greet(message)
      case message
        when "ge"
          "A Very Good Evening"
        else
          super(message)
      end
    end
  end
end

, а затем вы можете:

puts My::Greetings.greet("ge")
5 голосов
/ 04 мая 2011

Вы можете сделать что-то вроде этого, чтобы снова открыть класс в вашем коде:

Greetings.class_eval do
  class << self
    alias :old_greet :greet
  end
  def self.greet(message)
    return "a very good evening" if message == "ge"
    old_greet(message)
  end
end
3 голосов
/ 04 мая 2011

Вы могли бы сделать что-то вроде

class Greetings
  class << self
    alias :old_greet :greet
  end

  def self.greet(message)
    return "A very good evening" if message == 'ge'
    old_greet(message)
  end
end
0 голосов
/ 04 мая 2011

Как насчет этого, просто?

class Greetings
   def self.greet(message)
      return "good morning" if message=="gm"
      return "evening" if message=="ge"
      return "good afternoon" if message=="ga"
   end
end

class GreetingsOverloaded < Greetings
  def self.greet(message)
      return "A Very Good Evenin" if message=="ge"
      super
   end
end

puts Greetings.greet("ge")
puts GreetingsOverloaded.greet("ge")
...