此方法:
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
?
修改:这与问题无关,但请注意,没有“标题化”!方法
答案 0 :(得分:42)
每当你想在self上调用setter方法时,你必须编写self.foo = bar。如果你只是写foo = bar,那么ruby解析器会认为它是一个变量赋值,并且从现在开始认为foo是一个局部变量。为了让解析器能够实现,你想要调用一个setter方法,而不是分配一个局部变量,你必须编写obj.foo = bar,所以如果对象是self,那么self.foo = bar
答案 1 :(得分:7)
使用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”意味着Ruby的类关键字。