2009-03-06 10 views
40

Sé que estoy haciendo algo estúpido o no hago algo inteligente. Con frecuencia soy culpable de ambos.Rieles: no puedo llamar a una función en un módulo en/lib: ¿qué estoy haciendo mal?

He aquí un ejemplo de lo que me está causando dolor:

he un módulo guardado en/lib como test_functions.rb que tiene este aspecto

module TestFunctions 
    def abc 
    puts 123 
    end 
end 

Al entrar en ruby ​​script/corredor, puedo ver que el módulo se carga automáticamente (buen ol convención sobre la configuración y todo eso ...)

>> TestFunctions.instance_methods 
=> ["abc"] 

así se conoce el método, vamos a tratar llamándolo

>> TestFunctions.abc 
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):3 

Nope. ¿Qué tal esto?

>> TestFunctions::abc 
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):4 

Prueba Nope again.

defined?(TestFunctions::abc) #=> nil, but 
TestFunctions.method_defined? :abC#=> true 

Como dije en la parte superior, sé que estoy siendo tonto, ¿alguien puede decirme tonterías?

Respuesta

24

voy a tratar de resumir las diversas respuestas a mí mismo, ya que cada uno tenía algo valioso que decir, pero ninguno realmente conseguido a lo que ahora se dan cuenta es probablemente la mejor respuesta:

que estaba pidiendo el mal pregunta porque lo estaba haciendo mal.

Por razones que ya no puedo explicar, quería un conjunto de funciones completamente independientes en una biblioteca, que representaban los métodos que estaba tratando de eliminar de mis clases.Eso se puede lograr, utilizando cosas como

module Foo 
    def self.method_one 
    end 

    def Foo.method_two 
    end 

    class << self 
    def method_three 
    end 
    end 

    def method_four 
    end 

    module_function :method_four 
end 

pude también include mi módulo, ya sea dentro de una clase, en cuyo caso los métodos se convierten en parte de la clase o en el exterior, en cuyo caso se definen en cualquier clase I Estoy corriendo dentro (Objeto? Kernel? Irb, si soy interactivo? Probablemente no es una gran idea, entonces)

El hecho es que no había una buena razón para no tener una clase en primer lugar. De alguna manera me metí en una línea de pensamiento que me llevó a un ramal poco utilizado y francamente un poco raro. Probablemente un flashback de los días previos a OO se convirtió en una corriente principal (tengo edad suficiente como para que hasta hoy haya pasado muchos más años escribiendo código de procedimiento).

Así que las funciones se han movido a una clase, donde parecen muy felices, y los métodos de clase así expuestos se usan alegremente siempre que sea necesario.

4

es necesario incluir el módulo

include Testfunctions

Entonces 'abc' devolverá algo.

4

No puede llamar directamente a un método en un Módulo. Necesitas incluirlo en una clase. Prueba esto:

>> class MyTest 
>> include TestFunctions 
>> end 
=> MyTest 
>> MyTest.new.abc 
123 
=> nil 
+0

¿Has mirado la respuesta de Marcin? – m33lky

56

Si desea Module funciones -level, definirlos en cualquiera de estas maneras:

module Foo 
    def self.method_one 
    end 

    def Foo.method_two 
    end 

    class << self 
    def method_three 
    end 
    end 
end 

Todas estas formas harán que los métodos disponibles como Foo.method_one o Foo::method_one etc

Como han mencionado otras personas, los métodos de instancia en Module s son los métodos que están disponibles en los lugares donde tiene include d Module

23

También puede utilizar module_function así:

module TestFunctions 
    def abc 
    puts 123 
    end 

    module_function :abc 
end 

TestFunctions.abc # => 123 

Ahora puede incluir TestFunctions en clase y llamar "abc" de dentro del módulo TestFunctions.

4

Es necesario prefijar su función con el nombre del módulo, porque los módulos no son clases:

Su /lib/test_functions.rb:

module TestFunctions 
    def TestFunctions.abc 
    puts 123 
    end 
end 

Su código utilizando el método del módulo:

require 'test_functions' 
TestFunctions.abc 
6

Me metí en esto por un tiempo y aprendí varias cosas. Espero que esto ayude a alguien más a salir. Estoy ejecutando Rails 3.2.8.

Mi módulo (utilities.rb) se parece a esto y se encuentra en el directorio/lib de mi carriles de aplicación:

module Utilities 

    def compute_hello(input_string) 
    return "Hello #{input_string}" 
    end 

end 

Mi prueba (my_test.rb) se parece a esto y se encuentra en el directorio/prueba/directorio de la unidad de mi carriles de aplicación:

require "test_helper" 
require "utilities" 

class MyTest < ActiveSupport::TestCase 
    include Utilities 

    def test_compute_hello 
    x = compute_hello(input_string="Miles") 
    print x 
    assert x=="Hello Miles", "Incorrect Response" 
    end 

end 

Aquí están algunas cosas a tener en cuenta: mi prueba se extiende ActiveSupport :: TestCase. Esto es importante porque ActiveSupport agrega/lib a $ LOAD_PATH. (seehttp: //stackoverflow.com/questions/1073076/rails-lib-modules-and)

En segundo lugar, necesitaba "exigir" mi archivo de módulo y también "incluir" el módulo. Por último, es importante tener en cuenta que las cosas que se incluyen desde el módulo se colocan esencialmente en la clase de prueba. Entonces ... tenga cuidado de que el módulo que incluye no comience con "prueba_". De lo contrario, Rails intentará ejecutar su método de módulo como una prueba.

Cuestiones relacionadas