Попытка понять использование self.method_name против Classname.method_name в Ruby - PullRequest
13 голосов
/ 14 мая 2009

Я пытаюсь понять, когда использовать self.method_name и когда использовать Classname.method_name.

В приведенном ниже примере, почему «before_create» должен ссылаться на «User.hash_password» вместо «self.hash_password» или просто «hash_password»?

Поскольку мы уже находимся в классе User, я думал, что метод before_create будет «знать», что «hash_password» является членом своего собственного класса и ему не потребуется какой-либо специальный синтаксис для ссылки на него.

require 'digest/sha1'

class User < ActiveRecord::Base

  attr_accessor :password
  attr_accessible :name, :password

  validates_presence_of :name, :password
  validates_uniqueness_of :name

  def before_create
    self.hashed_password = User.hash_password(self.password)
  end

  def after_create
    @password = nil
  end

  def self.login(name, password)
    hashed_password = hash_password(password || "")
    self.find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password])
  end

  def try_to_login
    User.login(self.name, self.password)
  end

  private

  def self.hash_password(password)
    Digest::SHA1.hexdigest(password)
  end

end

Ответы [ 3 ]

13 голосов
/ 14 мая 2009
def before_create
   self.hashed_password = User.hash_password(self.password)
end

В этом примере User.hash_password вызывает метод hash_password для класса User, тогда как self.hashed_password= вызывает метод hashed_password= для этого конкретного экземпляра User.

Если вы замените User.hash_password на self.hash_password, Ruby будет жаловаться на NoMethodError, поскольку в классе User не существует метода экземпляра с именем hash_password. Вы можете заменить его на self.class.hash_password.

Если вы замените self.hashed_password= просто hashed_password=, Ruby создаст локальную переменную с именем hashed_password вместо вызова метода экземпляра hashed_password=. Вам нужно явно добавить self, если вы хотите вызвать средства записи атрибутов.

self в определении метода (def self.hash_password) делает hash_password методом класса вместо метода экземпляра. В этом контексте self относится к классу . В контексте метода экземпляра self относится к экземпляру .

12 голосов
/ 14 мая 2009

Вы спрашиваете разницу между методом класса и методом экземпляра.

Существует несколько способов определения метода класса:

class Klass
  def Klass.method_name
    ..
  end
end

, что аналогично действию:

class Klass
  def self.method_name
    ..
  end
end 

или предпочитаемая идиома рубина:

class Klass
  class << self
    def method_name
      ..
    end
  end
end

Если Класс уже объявлен, вы также можете сделать ..

def Klass.method_name
  ..
end

или:

class << Klass
  def method_name
    ..
  end
end

или вы можете даже использовать Модуль # extension:

Klass.extend(Module.new { def method_name; puts 'ducky'; end })

Так же, как вы бы добавили одноэлементный метод к объекту. Фактически методы класса - это одноэлементные методы, которые работают на уровне класса.

Например, в рельсах ActiveRecord у вас есть метод класса 'find', который вы можете использовать в любой модели:

Person.find(1) 

и экземпляры методов типа 'save', которые работают с отдельным объектом

person = Person.find(1)
...
person.save

В текущем проекте, над которым я работаю, у меня есть модель Feed, которая содержит каналы данных. Периодически мне нужно запускать метод, который обновляет все каналы, поэтому у меня есть метод fetch_all, который выполняет это.

class Feed < ActiveRecord::Base 

  // class method Feed.fetch_all
  def self.fetch_all
    Feed.all.each do |feed|
      feed.fetch_value
    end
  end

  // instance method
  def fetch_value
    // grabs updated value and saves 
  end
end
1 голос
/ 14 мая 2009

Мне еще предстоит углубиться в Ruby, но из вашего описания я бы сказал, что hash_password является статическим методом или может использоваться статическим способом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...