class Restaurant attr_accessor :average_rating, :city def initialize(city, name) @city = city @name = name @number_of_ratings = 0 @sum_of_ratings = 0 end def rate(new_rate) @number_of_ratings += 1 @sum_of_ratings += new_rate @average_rating = @sum_of_ratings.to_f / @number_of_ratings end def self.filter_by_city(restaurants, city) restaurants.select { |restaurant| restaurant.city == city } end end El código anterior es parte de un desafío y seguí fallando las pruebas para el método #filter_by_city. Revisé la solución y la única diferencia era el self. antes del nombre del método. He tratado de entender lo que hace exactamente el self , pero es difícil de entender sin contexto. En este método de clase particular, ¿qué está haciendo exactamente self mismo? Sé lo que está haciendo el cuerpo del método, es decir, filtrar los restaurantes por ciudad, pero ¿cómo funciona exactamente?
self es el Restaurant de clase. def self.method es cómo implementa un método en la clase misma en lugar de una instancia de la clase. Restaurant.filter_by_city(...) en lugar de Restaurant.new.filter_by_city(...) .
cambios self en Ruby dependiendo del contexto. Dentro de un método, self es el objeto al que se invocó el método.
Dentro del bloque de la class Restaurant , y fuera de cualquier método, self es el objeto Restaurant que es un objeto Class . Todo es un objeto en Ruby. Todo.
También puede hacer esto declarando un bloque donde la clase es la instancia.
class << self def filter_by_city(restaurants, city) restaurants.select { |restaurant| restaurant.city == city } end endNormalmente usaría esta sintaxis si tiene muchos métodos de clase.
Consulte Self in Ruby: A Comprehensive Overview para obtener más información.
Al definir un método en Ruby, puede opcionalmente definir explícitamente el receptor de ese método usando la sintaxis def <receiver>.<method> en lugar de def <method>
object = Object.new def object.foo :foo end object.foo #=> fooEl receptor debe ser una referencia singular O una expresión (pero debe estar entre corchetes):
a = [Object.new, Object.new] def (a.first).foo :foo end def (a[1]).bar :bar end a[0].foo #=> :foo a.last.bar #=> :bar a.first.bar #=> undefined methodCuando se define el receptor, el método se define directamente en la clase singleton del receptor, ignorando el contexto en el que se define el método:
class A o = Obejct.new def o.foo end end A.new.foo #=> undefined methodAunque el método foo se definió en el cuerpo de la clase A, no está disponible para sus instancias debido al receptor explícito
self es una palabra clave de Ruby que devuelve el "contexto" actual. Dentro de los métodos, self es (normalmente) un receptor de la llamada, y dentro del módulo self devuelve ese módulo. Asi que:
module Wrapper module SomeModule puts self.name end end imprimirá Wrapper::SomeModule .
Esto significa que:
class A def self.foo end endEs exactamente lo mismo que:
class A def A.foo end end Por lo tanto, el método se define directamente en A y solo se puede llamar directamente en la clase como A.foo , en lugar de en sus instancias.