добавление специфичной для класса функциональности в модулях ruby - PullRequest
1 голос
/ 19 января 2012

возможно, я не очень хорошо объясняю эту концепцию, но я хочу добавить методы класса к ряду классов ruby, чтобы они могли содержать специфичную для класса информацию, которая затем будет вызываться отдельными методами экземпляров классов.

Я могу заставить это работать, но это немного уродливо. Может кто угодно, так как для этого требуется 2 модуля, один из которых включен, а другой расширенный (см. Пример кода ниже).

Кто-нибудь может придумать более элегантный способ реализации этой функциональности?

Спасибо

Steve

Этот модуль расширен для предоставления методов класса, но добавляет член экземпляра в каждый класс, в который он включен

module My1
   def my_methods (*sym_array)
     @my_methods=sym_array
   end

   def method_list
      @my_methods
   end
end

Этот модуль включен для предоставления методов экземпляра

module My2
   def foo
      self.class.method_list.each { |m| self.send m }
   end
end

Теперь используйте модули - уродство должно использовать оператор include и extends, чтобы позволить мне передать набор символов в метод класса, который затем будет реализован в Экземпляр

class Foo
   extend My1
   include My2

   my_methods :baz

   def baz
      puts "Baz!"
   end
end

class Bar
   extend My1
   include My2

   my_methods :frodo

   def frodo
      puts "Frodo!"
   end

end

class Wibble < Bar
   extend My1
   include My2

   my_methods :wobble

  def wobble
     puts "Wobble!"
  end
end

Вот требуемый вывод - обратите внимание, что у каждого класса есть свой экземпляр @my_methods, поэтому поведение производного класса Wibble отличается.

f=Foo.new
b=Bar.new
w=Wibble.new

f.foo #=> "Bar!"
b.foo #=> "Frodo!"
w.foo #=> "Wobble!"

Ответы [ 2 ]

3 голосов
/ 19 января 2012

Когда модуль включен, к нему вызывается хук.Вы можете использовать это для расширения, которое вы хотите.

module M1
  def self.included(base)
    base.extend(M2)
  end
end

Люди часто называют этот второй модуль M1::ClassMethods.Если вы используете рельсы, ActiveSupport::Concern инкапсулирует этот шаблон

1 голос
/ 19 января 2012

Я бы предложил вместо этого использовать ловушку из модуля:

module MyModule
  def self.included(klass)
    klass.extend ClassMethods
  end

  def foo
    self.class.method_list.each{ |m| self.send m }
  end

  module ClassMethods
    attr_reader :method_list

    def my_methods(*sym_array)
      @method_list = sym_array
    end
  end
end

Таким образом, будет проще вызывать включение только модуля всякий раз, когда вы хотите функциональность для данных классов.

class Foo
  include MyModule

   my_methods :baz

   def baz
      puts "Baz!"
   end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...