2010-03-22 14 views
12

Spero di implementare qualcosa di simile a tutte le grandi plugin là fuori per rubino, in modo che si può fare questo:Passa gli argomenti al modulo incluso in Ruby?

acts_as_commentable 
has_attached_file :avatar 

Ma io ho un vincolo:

Questo metodo di supporto può includere solo un modulo; non può definire alcuna variabile o metodo.

La ragione di questo è perché, voglio che le opzioni di hash per definire qualcosa come type, e che potrebbe essere convertito in una delle dicono 20 moduli diversi 'cavallo di battaglia', ognuno dei quali potessi riassumere in una linea in questo modo:

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

Poi quelle 'cavalli di lavoro' sarebbe gestire le opzioni, fare le cose come:

has_many "#{options[:something]}" 

Ecco cosa la struttura assomiglia, e mi chiedo se si sa t egli pezzo mancante del puzzle:

# 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!" 

Che %Q? io non sono del tutto sicuro di come usare, ma io sono fondamentalmente solo voler essere in qualche modo in grado di passare il options hash da quel metodo di supporto nel modulo cavallo di battaglia . È possibile? In questo modo, il modulo workhorse poteva definire tutti i tipi di funzionalità, ma potevo nominare le variabili come volevo al runtime.

risposta

2

si potrebbe desiderare di guardare il Modularity gemma , che fa esattamente quello che vuoi.

3

Sto lavorando a qualcosa di simile, basato su un intelligente codice rubino che ho visto una volta ma che ora non riesco a trovare di nuovo. Ho cose che funzionano allo quasi, ma rovinano cose come self.included e self.extended nel tuo modulo, per ragioni abbastanza ovvie che potrebbero essere risolte, ma non mi piace quanto sarebbe complicato. Penso che ci sia un trucco che non ho ancora pensato per rendere questo lavoro più perfetto.

Quindi questo può o non può funzionare per voi, ma quello che sto provando è l'idea di un modulo anonimo creato dinamicamente in base alle vostre opzioni. (Penso che "tipo" potrebbe essere una parola riservata ma non ne sono sicuro, quindi diciamo "opzioni"). Dai un'occhiata a questa idea:


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 } 

Tipo di pulito, eh? Ma non è ancora abbastanza buono per me, perché il modulo reale che si ottiene da HelperModule [opzioni] non ha il sé. Incluso e auto.esteso dall'HelperModule originale. Credo che potrei solo definire self.included e self.extended nel modulo anon, ma non mi piace la confusione del codice. Inoltre non mi piace dover dire esplicitamente "include HelperModule" nel modulo anonimo, preferisco che sia, come "self", eccetto "self" non significa la cosa giusta lì, quindi non funziona .

Ah, aspetta, indovinate un po 'ho appena scoperto: Se questo approccio generale sembra che dovrebbe funzionare per voi, può essere fornito dalla gemma Paramix: http://rubyworks.github.com/paramix/

0

ActionModel gem può aiutarti. Lo uso nei miei progetti.

+0

Puoi approfondire come questo potrebbe essere d'aiuto in questo caso?Potrebbe essere ovvio per te, ma le buone risposte su questo sito includono questo tipo di informazioni. Un puntatore senza una spiegazione non è in realtà una risposta .... – GreenAsJade

+0

It's acts_as DSL for ruby ​​class. Puoi passare campi e opzioni in azione (modulo), ad esempio act_as_searchable: title, ignorecase: true –

Problemi correlati