71 votes

Appels de méthodes Ruby déclarés dans la classe body

Je viens de commencer à apprendre ruby on rails et j'ai rencontré du code comme ci-dessous :

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

Il y a deux appels de méthode dans le corps de la classe. J'ai eu beaucoup de mal à trouver de la documentation ruby qui décrivant comment fonctionnent les appels de méthode à l'intérieur du corps d'une classe (mais en dehors de toute méthode). Tous les livres que j'ai, décrivent seulement comment définir les méthodes de classe et d'instance et comment les appeler à partir d'autres méthodes. comment les appeler depuis d'autres méthodes.

Les questions que je me pose sont les suivantes : Comment et quand ces méthodes sont-elles appelées ? Comment sont-elles définies ? S'agit-il de mixins définis dans un module d'enregistrement actif ?

37voto

Chuck Points 138930

Le corps d'une définition de classe est un contexte d'exécution de code comme un autre. Le code qui s'y trouve est exécuté dans le contexte de la classe (c'est-à-dire que self est l'objet classe, qui est une instance de Class). Vous pouvez avoir des variables locales et des variables d'instance (qui appartiendront à l'objet de classe lui-même plutôt qu'aux instances de la classe) et vous pouvez appeler n'importe quelle méthode à laquelle l'objet de classe répond. Le code est exécuté une fois que le bloc de définition de la classe est terminé.

Dans ce cas, ActiveRecord::Base définit les méthodes de la classe validates_presence_of et belongs_to .

18voto

John Topley Points 58789

Yehuda Katz a une bonne explication à ce sujet sur son blog. Voir le point 4 : Les corps de classe ne sont pas spéciaux .

13voto

Larry K Points 16266
Re: How and when are these methods called?

Ils sont appelés lorsque la classe est chargée. Vous pouvez placer un point d'arrêt dans l'une des méthodes et constater qu'elle est appelée lors du démarrage de votre projet rails.

How are they defined?

Ce sont des méthodes de classe. Comme il s'agit de ruby, elles peuvent être définies de plusieurs façons.

Are they mixins defined in some active record module?

Dans ce cas, validates_presence_of est défini dans vendor/rails/activerecord/lib/active_record/validations.rb et belongs_to est défini dans vendor/rails/activerecord/lib/active_record/associations.rb . ActiveRecord est un grand système, qui comprend de nombreux mixins, modules, etc.

Note, pour voir où les méthodes sont définies, j'utilise http://www.gotapi.com/rubyrails pour chaque méthode, voir le lien "Show Source" au bas de la définition.

12voto

Corban Brook Points 8836

Il s'agit de méthodes de classe ou de méthodes "singleton". L'une d'entre elles, attr_accessor, devrait vous être familière. Nous pouvons implémenter une méthode similaire dans une classe de test.

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

Dans l'exemple ci-dessus, nous avons créé la méthode de classe avec 'def self.add_getter_and_setter' mais ce n'est pas la seule façon.

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

Utilisation de la méthode extend. Module#extend est une méthode qui étend une classe avec des méthodes de classe, de même que la méthode Module#include inclut une classe avec des méthodes d'instance.

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

Si Klass a déjà été défini nous pouvons le rouvrir pour ajouter des méthodes de classe

class Klass
end

def Klass.add_getter_and_setter(symbol)
  ..
end

# or 

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

Ce sont les quelques méthodes que je connais pour faire cela, donc si vous voyez différentes syntaxes, réalisez simplement qu'elles font toutes la même chose.

Remarque : dans les rails, une méthode de classe commune que nous utilisons tous est "find". Elle est exécutée directement à partir de la classe Model.

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

3voto

Cody Caughlan Points 18780

Ce que vous voyez, ce sont des méthodes de niveau classe pour un objet ActiveRecord. Pour écrire vos propres méthodes qui fonctionnent de la même manière, vous devez les écrire en tant que plugin et les inclure ensuite dans ActiveRecord en rouvrant la définition de la classe. Le guide Ruby on Rails pour créer un plugin :

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

Couvre la manière d'écrire un tel plugin / méthodes de niveau classe. Il s'agit d'un bon document sur la façon de comprendre ce que ces types de méthodes signifient et comment elles interagissent avec les instances.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X