Rails模型中self的价值是什么?为什么没有明显的实例方法可用?

我的rails 3.1.6应用程序中有一个自定义访问器方法,它为属性赋值,即使该值不存在.my_attr属性是一个序列化的哈希值,除非指定了空值,否则应与给定值合并,在这种情况下,它会将当前值设置为空值。 (增加了检查以确保值是它们应该是什么,但为了简洁而删除,因为它们不是我的问题的一部分。)我的setter定义为:

def my_attr=(new_val) cur_val = read_attribute(:my_attr) #store current value #make sure we are working with a hash, and reset value if a blank value is given write_attribute(:my_attr, {}) if (new_val.nil? || new_val.blank? || cur_val.blank?) #merge value with new if cur_val.blank? write_attribute(:my_attr, new_val) else write_attribute(:my_attr,cur_val.deep_merge(new_val)) end read_attribute(:my_attr) end 

这段代码按原样运行,但是当我使用self.write_attribute()时则不行。 然后我收到以下错误:

 NoMethodError: private method `write_attribute' called for # 

因此我的问题是:让一个实例可以使用write_attribute似乎更合乎逻辑,那么为什么它只适用于类而不是实例? 在Ruby或Rails(或两者)中,我对自我的基本知识缺乏什么?

在实例方法中, self就是那个实例。 但是,当您使用显式接收器调用方法时,ruby的可见性控制将启动并禁止调用私有方法。

 class Foo def implicit self # => # private_method end def explicit self # => # self.private_method end private def private_method "bar" end end f = Foo.new f.implicit # => "bar" f.explicit # => # ~> -:9:in `explicit': private method `private_method' called for # (NoMethodError) # ~> from -:25:in `
'

如果要调用私有方法,请使用隐式接收器或send

 self.send :private_method 

更新

ruby元编程书的摘录。

私人真正意味着什么

现在你了解了self,你可以对Ruby的私有关键字有所了解。 私有方法由一个简单的规则控制:您不能使用显式接收器调用私有方法。 换句话说,每次调用私有方法时,它必须位于隐式接收器自身上。 让我们看一个角落案例:

 class C def public_method self.private_method end private def private_method; end end C.new.public_method ⇒ NoMethodError: private method 'private_method' called [...] 

您可以通过删除self关键字来使此代码生效。

这个人为的例子表明私有方法来自两个一起工作的规则:首先,你需要一个显式接收器来调用一个不是你自己的对象的方法,其次,私有方法只能用一个隐式接收器来调用。 将这两个规则放在一起,您将看到您只能自己调用​​私有方法。 你可以称之为“私人规则”。

您可能会发现Ruby的私有方法令人困惑 – 特别是如果您来自Java或C#,其中私有行为的表现非常不同。 如果您有疑问,只需回到私人规则,一切都会有意义。 如果两个对象共享同一个类,对象x可以在对象y上调用私有方法吗? 答案是否定的,因为无论你属于哪个类,你仍然需要一个明确的接收器来调用另一个对象的方法。 你能调用一个从超类inheritance的私有方法吗? 答案是肯定的,因为您不需要显式接收器来自行调用inheritance的方法。