2009-08-09 16 views
9

Questo metodo:Quando usare 'sé' in Ruby

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 

riesce con questo errore quando date è nullo:

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' 

Tuttavia, se cambio date = date.to_date-self.date = self.date.to_date, il metodo funziona correttamente .

Cosa sta succedendo? In generale, quando devo scrivere self?

Modifica: Non è correlato alla domanda, ma si ricorda che non esiste "titleize!" metodo.

+0

possibile duplicato del [Perché setter rubino bisogno di "sé". qualifica all'interno della classe?] (http://stackoverflow.com/questions/44715/why-do-ruby-setters-need-self-qualification-within-the-class) –

risposta

42

Ogni volta che si vuole invocare un metodo setter su di sé, si deve scrivere self.foo = bar. Se scrivi semplicemente foo = bar, il parser ruby ​​riconosce che come assegnazione di variabile e pensa a foo come variabile locale da ora in poi. Per far sì che il parser realizzi, che tu invochi un metodo setter e non assegni una variabile locale, devi scrivere obj.foo = bar, quindi se l'oggetto è self, self.foo = bar

7

Tu disambiguare tra il nome del metodo di istanza e una variabile locale utilizzando self (è consentito avere entrambi con lo stesso nome nello stesso ambito). In altre parole, ci sarà una risoluzione del nome del metodo solo se non ci sono variabili locali o di blocco con lo stesso nome in ambito. Ecco:

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

Ecco perché: immagina di avere un modulo che implementa un metodo. Questo metodo assegna qualcosa alla sua variabile locale interna "foo" che viene utilizzata per alcuni calcoli. Se salti la parte "self", il metodo eseguirà una chiamata al metodo "foo =" sull'oggetto la cui classe include il modulo, che non era l'intenzione dell'autore e può essere addirittura disastroso.

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) 

Un'altra parte cruciale in cui si deve utilizzare auto è quando si richiama il metodo della classe Object #, perché semplicemente dicendo "classe": una parola chiave class per Ruby.