gpt4 book ai didi

ruby-on-rails - self 在 Rails 模型中的值(value)是什么?为什么没有明显的实例方法可用?

转载 作者:数据小太阳 更新时间:2023-10-29 07:11:40 24 4
gpt4 key购买 nike

我的 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 #<MyModel:0x00000004f10528>

因此我的问题是:write_attribute 对实例可用似乎更符合逻辑,那么为什么它只对类可用而对实例可用?我对 Ruby 或 Rails(或两者)self 的基本知识是否有所欠缺?

最佳答案

实例方法内部 self 就是那个实例。但是,当您调用带有显式接收器的方法时,ruby 的可见性控制就会启动并禁止调用私有(private)方法。

class Foo
def implicit
self # => #<Foo:0x007fc019091060>
private_method
end

def explicit
self # => #<Foo:0x007fc019091060>
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 #<Foo:0x007fc019091060> (NoMethodError)
# ~> from -:25:in `<main>'

如果要调用私有(private)方法,请使用隐式接收方或发送

self.send :private_method

更新

摘自 ruby metaprogramming book .

What private Really Means

Now that you know about self, you can cast a new light over Ruby’s private keyword. Private methods are governed by a single simple rule: you cannot call a private method with an explicit receiver. In other words, every time you call a private method, it must be on the implicit receiver—self. Let’s see a corner case:

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 [...]

You can make this code work by removing the self keyword.

This contrived example shows that private methods come from two rules working together: first, you need an explicit receiver to call a method on an object that is not yourself, and second, private methods can be called only with an implicit receiver. Put these two rules together, and you’ll see that you can only call a private method on yourself. You can call this the “private rule.”

You could find Ruby’s private methods perplexing—especially if you come from Java or C#, where private behaves very differently. When you’re in doubt, just go back to the private rule, and everything will make sense. Can object x call a private method on object y if the two objects share the same class? The answer is no, because no matter which class you belong to, you still need an explicit receiver to call another object’s method. Can you call a private method that you inherited from a superclass? The answer is yes, because you don’t need an explicit receiver to call inherited methods on yourself.

关于ruby-on-rails - self 在 Rails 模型中的值(value)是什么?为什么没有明显的实例方法可用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11461262/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com