2011-06-29 23 views
14

tengo un módulo de seguirRubí incluir un único método de módulo en el modelo

module SimpleTask 
    def task1 
    end 
    def task2 
    end 
    def task3 
    end 
end 

Y tengo un modelo que requiere sólo task2 método del módulo de SimpleTask.

Lo sé incluyendo SimpleTask en mi modelo con include SimpleTask haría el trabajo.

Pero me pregunto si solo puedo incluir el método específico task2 en mi modelo.

+0

posible duplicado de [¿Puedo invocar un método de instancia en un módulo de Ruby sin incluirlo?] (Http://stackoverflow.com/questions/322470/can-i-invoke-an-instance-method-on-a -ruby-module-without-including-it) –

Respuesta

6

Parece que necesita refactorizar #task2 en un módulo aparte (por ejemplo, BaseTask). Luego puede incluir fácilmente solo BaseTask donde solo necesita #task2.

module BaseTask 
    def task2 
    ... 
    end 
end 

module SimpleTask 
    include BaseTask 

    def task1 
    ... 
    end 

    def task3 
    ... 
    end 
end 

Es difícil ayudar mucho más sin una pregunta más concreta (como la interdependencia entre los métodos de SimpleTask, etc.

Usted podría hacer algunas meta-programación donde include SimpleTask y luego undefine la métodos que no quieren, pero eso es bastante feo OMI.

3

se podría añadir

module SimpleTask 
    def task1 
    end 
    def task2 
    end 
    def task3 
    end 
    module_function :task2 
end 

De modo que usted puede llamar al método como un método de clase en el módulo, además de tener como un método de instancia en los lugares que hace quieren los tres métodos, es decir:

class Foo 
    include SimpleTask 
end #=> Foo.new.task2 
class LessFoo 
    def only_needs_the_one_method 
     SimpleTask.task2 
    end 
end #=> LessFoo.new.only_needs_the_one_method 

O, si realmente no hay estado compartido en el módulo y no te importa utilizar siempre el nombre del módulo en sí, puede declarar todos los métodos de clase de nivel, así:

module SimpleTask 
    def self.task1 
    end 
    def self.task2 
    end 
    def self.task3 
    end 
end 

class Foo 
    include SimpleTask # Does, more or less nothing now 
    def do_something 
    SimpleTask.task1 
    end 
end 
#=> Foo.new.task2 #=> "task2 not a method or variable in Foo" 
#=> Foo.new.do_something does, however, work 
class LessFoo 
    def only_needs_the_one_method 
     SimpleTask.task2 
    end 
end #=> LessFoo.new.only_needs_the_one_method works as well in this case 

pero tendría que cambiar todo el llamantes en ese caso.

5

voy a robar un ejemplo de delegate.rb, restringe lo que incluye

... 
class Delegator < BasicObject 
    kernel = ::Kernel.dup 
    kernel.class_eval do 
    [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m| 
     undef_method m 
    end 
    end 
    include kernel 
... 

convierte

module PreciseInclude 

    def include_except(mod, *except) 
    the_module = mod.dup 
    the_module.class_eval do 
     except.each do |m| 
     remove_method m # was undef_method, that prevents parent calls 
     end 
    end 
    include the_module 
    end 
end 

class Foo 
    extend PreciseInclude 

    include_except(SimpleTask, :task1, :task2) 
end 

Foo.instance_methods.grep(/task/) => [:task3] 

que siempre puede darle la vuelta así que en vez de incluirlo convierte include_only

El inconveniente es que remove_method no funcionará para módulos anidados, y el uso de undef evitará buscar en toda la jerarquía ese método.

Cuestiones relacionadas