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

Передавать аргументы в модуль в Ruby?

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

acts_as_commentable
has_attached_file :avatar

Но у меня есть одно ограничение:

Этот вспомогательный метод может включать только модуль; он не может определить какие-либо переменные или методы.

Причина этого заключается в том, что я хочу, чтобы хэш параметров определял что-то вроде type, и это могло быть преобразовано в один из 20 различных модулей "рабочая лошадка", все из которых я мог бы суммировать в строке типа это:

def dynamic_method(options = {})
 include ("My::Helpers::#{options[:type].to_s.camelize}").constantize(options)
end

Тогда эти "рабочие лошадки" будут обрабатывать варианты, делая такие вещи, как:

has_many "#{options[:something]}"

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

# 1 - The workhorse, encapsuling all dynamic variables
module My::Module
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      include InstanceMethods
    end
  end

  module InstanceMethods
    self.instance_eval %Q?
      def #{options[:my_method]}
        "world!"
      end
    ?
  end

  module ClassMethods
  end
end

# 2 - all this does is define that helper method
module HelperModule
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods

    def dynamic_method(options = {})
      # don't know how to get options through!
      include My::Module(options)
    end

  end
end

# 3 - send it to active_record
ActiveRecord::Base.send(:include, HelperModule)

# 4 - what it looks like
class TestClass < ActiveRecord::Base
  dynamic_method :my_method => "hello"
end

puts TestClass.new.hello #=> "world!"

Это %Q? Я не совсем уверен, как использовать, но я просто хочу как-то передать хеш options из этого вспомогательного метода в модуль рабочей лошади. Это возможно? Таким образом, модуль рабочей лошадки мог бы определять всевозможные функциональные возможности, но я мог бы назвать переменные, которые мне нужны во время выполнения.

4b9b3361

Ответ 1

Возможно, вы захотите посмотреть Modularity gem, который делает именно то, что вы хотите.

Ответ 2

Я работаю над чем-то подобным, основанным на некотором умном коде Ruby, который я видел один раз, но теперь не могу найти снова. У меня есть вещи, которые почти работают, но это путается с такими вещами, как self.included и self.extended в вашем модуле, по несколько очевидным причинам, которые можно было бы проработать, но мне не нравится, насколько это будет сложно. Я думаю, там один трюк, о котором я еще не думал, что сделало бы эту работу более совершенной.

Таким образом, это может работать или не работать для вас, но я пытаюсь создать анонимный модуль, созданный динамически на основе ваших опций. (Я думаю, что "тип" может быть зарезервированным словом, но я не уверен, так что скажем "варианты" вместо этого). Ознакомьтесь с этой идеей:


Module HelperModule
   def[](options)
      Module.new do 
        include HelperModule
        define_method(:options) { options }
      end
   end

   def options
     raise TypeError.new("You need to instantiate this module with [], man!")
   end
end

obj = Object.new
obj.extend(HelperModule)
obj.options => raises TypeError

obj = Object.new
obj.extend(HelperModule[ :my_option => "my_option" ]
obj.options => { my_option => "my_option }

Вид аккуратный, да? Но пока еще недостаточно для меня, потому что фактический модуль, который вы получаете из HelperModule [options], не имеет self.included и self.extended из исходного HelperModule. Думаю, я мог бы просто определить self.included и self.extended в модуле анонов, но мне не нравится путаница кода. Мне также не нравится явно говорить "включить HelperModule" в анонимный модуль, я бы предпочел, чтобы это было, как "я", кроме "я", это не значит, что это правильно, так что это не работает,

А, подождите, угадайте, что я только что обнаружил: если этот общий подход кажется, что он должен сработать для вас, он может быть поставлен с помощью paramix gem: http://rubyworks.github.com/paramix/

Ответ 3

ActionModel gem может вам помочь. Я использую его в своих проектах.