假设我的模型Foo
带有bar
列。
我习惯于定义模型的实例方法,如下所示:
class Foo < ActiveRecord::Base
def do_smth
self.bar.capitalize!
end
end
但这是在self
上调用getter方法,它应该只是@bar.capitalize!
的更长的方式。
就像在Rails中一些东西是隐藏的(例如初始化Base
类)我不确定。它会起作用吗?
答案 0 :(得分:1)
这里有很多混乱,所以让我们从顶部开始:
Ruby是关于消息传递的 - 当你在对象上调用方法时,隐式接收者就是对象本身:
def do_smth
self.bar.capitalize!
end
相当于:
def do_smth
bar.capitalize!
en
所以让我们举几个例子:
class Thing
def initialize
@foo = 1
end
def test
foo # NameError: undefined local variable or method `foo'
end
def test2
@bar # nil
end
end
那么,为什么这会失败?因为在Ruby中,实例变量的范围限定为实例,并且只能使用sigil @
访问。 Ruby不会自动将@foo
映射到Thing#foo
。实例变量Ruby甚至允许您访问未初始化的ivars(@bar
)。
除非我们创建一个访问者:
class Thing
def foo
@foo
end
def test
foo # nil
end
end
可以使用速记宏attr_reader
和attr_accessor
来完成。
class Thing
attr_reader :foo # read only
attr_accessor :foo # rw
def test
foo # nil
end
end
如果您从Rails开始而不了解Ruby如何执行OOP,这可能会非常令人困惑,因为Active Record会读取您的数据库表并创建getter和setter&#34;神奇地&#34;适用于所有模型属性。
在这种情况下你需要记住的一件事是使用@some_column
不会调用任何getter / setter方法。这可能会导致Rails脏状态跟踪问题,以及在设置器中进行类型转换的日期列等情况。