Когда использовать «себя» в Ruby - PullRequest
9 голосов
/ 09 августа 2009

Этот метод:

  def format_stations_and_date
    from_station.titelize! if from_station.respond_to?(:titleize!)
    to_station.titleize! if to_station.respond_to?(:titleize!)
    if date.respond_to?(:to_date)
      date = date.to_date
    end
  end

Сбой с этой ошибкой, когда date равен нулю:

NoMethodError (You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_date):
  app/models/schedule.rb:87:in `format_stations_and_date'
  app/controllers/schedules_controller.rb:15:in `show'

Однако, если я изменю date = date.to_date на self.date = self.date.to_date, метод будет работать правильно.

Что происходит? В общем, когда мне нужно писать self?

Редактировать: Это не связано с вопросом, но, пожалуйста, обратите внимание, что здесь нет "titleize!" способ.

Ответы [ 2 ]

42 голосов
/ 09 августа 2009

Всякий раз, когда вы хотите вызвать метод set для self, вы должны написать self.foo = bar. Если вы просто напишите foo = bar, анализатор ruby ​​распознает это как присваивание переменной и с этого момента думает о foo как о локальной переменной. Чтобы синтаксический анализатор понял, что вы хотите вызвать метод установки, а не назначать локальную переменную, вы должны написать obj.foo = bar, поэтому, если объект является self, self.foo = bar

7 голосов
/ 10 августа 2009

Вы устраняете неоднозначность между именем метода экземпляра и локальной переменной, используя self (разрешено иметь оба одинаковых имени в одной и той же области видимости). Другими словами, разрешение имени метода будет иметь место только в том случае, если в области нет локальной или блочной переменной с тем же именем. Вот:

class Foo
  attr_accessor :boo
  def do_boo
    boo = 123
    puts "Locvar: #{boo} Method: #{self.boo}"
  end
end
Foo.new.do_boo

И вот почему: представьте, что у вас есть модуль, который реализует метод. Этот метод присваивает что-то своей внутренней локальной переменной «foo», который используется для некоторых вычислений. Если вы пропустите часть «self», метод вызовет метод «foo =» для объекта. чей класс включает модуль, который не был намерением автора и может быть совершенно катастрофическим.

class Foo
  def bar=(new_value_of_bar)
    set_off_nukes(new_value_of_bar / 3)
  end
end

module InnocentModule # written by a different author elsewhere
  def do_useful_stuff
    ...
    bar = Math.sin(something) # we're dead
  end
end
Foo.send(:include, InnocentModule)

Другая важная часть, где вы должны использовать self, - это вызов метода Object # class, потому что просто сказать «class» означает ключевое слово class для Ruby.

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