2009-08-28 12 views
51

Me acaban de comenzar el rubí en los carriles de aprendizaje y se han encontrado con un código como a continuación:llamadas Rubí método declarado en el cuerpo de la clase

class Post < ActiveRecord::Base 
validates_presence_of :title 
belongs_to :user 
end 

hay dos llamadas de método en el interior del cuerpo de la clase. Me ha costado encontrar cualquier documentación de ruby ​​que describa cómo funcionan las llamadas a métodos desde un cuerpo de una clase (pero fuera de cualquier método). Todos los libros que tengo, solo describen cómo definir los métodos de clase e instancia y cómo llamarlos a desde otros métodos.

Las preguntas que tengo son: ¿Cómo y cuándo se llaman estos métodos? ¿Cómo se definen? ¿Están mixins definidos en algún módulo de registro activo?

Respuesta

3

Lo que está viendo son métodos de nivel de clase para un objeto ActiveRecord. Para escribir sus propios métodos que funcionan de esta manera, los debería escribir como un complemento y luego incluirlos en ActiveRecord volviendo a abrir la definición de la clase. El rubí en los carriles guía para crear un plugin:

http://guides.rubyonrails.org/plugins.html

explica cómo se podría escribir un plugin de este tipo de métodos/a nivel de clase. Es un buen documento sobre cómo entender lo que significan estos tipos de métodos y cómo interactúan con las instancias.

+1

Una gema también funciona. –

11

Re: ¿Cómo y cuándo se llaman estos métodos?

[Se llaman cuando se carga la clase. Puede poner un punto de interrupción en uno de los métodos y ver que se llama como parte del inicio de su proyecto de raíles.]

¿Cómo se definen?

[Son métodos de clase. Como esto es ruby, se pueden definir de varias maneras.]

¿Están mixins definidos en algún módulo de registro activo?

[En este caso,

validates_presence_of se define en vendedor/carriles/activerecord/lib/active_record/validations.rb

belongs_to se define en vendedor/carriles/activerecord/lib/active_record/associations.rb

ActiveRecord es un gran sistema, incluye muchas mixins, módulos, etc.

Nota, para ver donde se definen los métodos, utilizo http://www.gotapi.com/rubyrails para cada método, consulte el enlace "Mostrar origen" en la parte inferior de la definición.

]

29

El cuerpo de una definición de clase es un contexto de ejecución de código al igual que cualquier otra. El código se ejecuta dentro del contexto de la clase (lo que significa self es el objeto de clase, que es una instancia de Clase). Puede tener locales y variables de instancia (que pertenecerán al objeto de clase en sí en lugar de instancias de la clase) y puede llamar a cualquier método al que responda el objeto de clase. El código se ejecuta una vez que el bloque de definición de clase finaliza.

En este caso, ActiveRecord :: Base define los métodos de clase validates_presence_of y belongs_to.

11

Estos son métodos de clase o métodos 'singleton'. Uno con el que debe estar familiarizado es attr_accessor. Podemos implementar algo así en una clase de prueba.

class Klass 
    def self.add_getter_and_setter(symbol) 
    module_eval "def #{symbol}; @#{symbol}; end" 
    module_eval "def #{symbol}=(val); @#{symbol} = val; end" 
    end 
end 

class Person < Klass 
    add_getter_and_setter :name 
    add_getter_and_setter :phone 
end 

person = Person.new 
person.name = 'John Smith' 
person.phone = '555-2344' 
person # returns <Person:0x28744 @name="John Smith", @phone="555-2344"> 

En el ejemplo anterior hemos creado el método de clase con 'def self.add_getter_and_setter', pero esto no es la única manera.

class Klass 
    class << self # opens the singleton class 
    def add_getter_and_setter(symbol) # note we dont specify self as it is already within the context of the singleton class 
     .. 
    end 
    end 
end 

Uso de extender. Module # extends es un método que amplía una clase con métodos de clase, así como el método Module #include incluye una clase con métodos de instancia.

class Klass 
    extend(Module.new do 
    def add_getter_and_setter(symbol) 
     .. 
    end 
    end) 
end 

Si Klass ya se ha definido, podemos volver a abrirlo para agregar métodos de clase

class Klass 
end 

def Klass.add_getter_and_setter(symbol) 
    .. 
end 

# or 

class << Klass 
    def add_getter_and_setter(symbol) 
    .. 
    end 
end 

Bueno esas son algunas de las formas que conozco cómo hacer esto así que si ves sintaxis diferente sólo se dan cuenta es todo haciendo lo mismo

Nota: en los rieles, un método de clase común que todos usamos es 'encontrar'. Se ejecuta directamente fuera de la clase Modelo.

person = Person.find(1) # finds a person with id:1 
Cuestiones relacionadas