比如有一个 class
class Log
include Mongoid::Document
include Mongoid::Timestamps::Created
field :task_ids, type: Array ,:default => []
protected
before_save :save_task_ids
def save_task_ids
task_ids = somevalue
end
end
我测试下来 task_ids= 这句话被理解为给一个局部变量赋值了,如果是要给 field 赋值,必须是用 self.task_ids= 请问在 ruby 里如果隐含调用 self 的实例方法,是否局部变量赋值优先于 self 的 setter 方法?
局部变量不存在的时候不会。 从你例子的情况看,是因为 db 属性字段都是通过 method missing 实现的,其实 task_ids=这个方法还没定义。
赋值方法一定要显示调用 self。ruby 看到赋值语句就会建立一个局部变量,即使没有实际运行
class A
def name=(name)
@name = name
end
def name
"Class A"
end
def test_setter
name = "A"
p name #=> "A"
p @name #=> nil
end
def test_scope
p name #=> "Class A"
name = "A" if false
p name #=> nil
end
end
#9 楼 @night_song 我觉得 define_method 似乎和直接定义 method 没区别阿.. 确定是 local variable 优先吗?
class A
attr_accessor :name
def initialize name
@name = name
end
def change_name
change_me
end
private
def change_me
puts %(
puts name #=> #{name}\n
puts self.name #=> #{self.name}\n
puts name=bar;self.name #=> #{name='bar';self.name}\n
puts name #=> #{name}
puts self.methods.eql?(methods) #=> #{self.methods.eql?(methods)}\n
puts send(:name=,'bar');self.name #=> #{send(:name=,'bar');self.name}
)
end
end
a = A.new "foo"
a.change_name
输出结果
puts name #=> foo
puts self.name #=> foo
puts name=bar;self.name #=> foo
puts name #=> bar
puts self.methods.eql?(methods) #=> true
puts send(:name=,'bar');self.name #=> bar
可见 self 也被 'private'了
其实 task_id 读写是在 field :task_ids, type: Array ,:default => [] 定义的,这里没必要用 method_missing ...
其实规则很简单 ... a = x 总是赋值语句而不是方法调用 a.b = x 总是方法调用
即使 setter 是 public method,也必须明确前缀 self,这是 ruby 中一个特例。 另外 setter 是 private 或 protected method 的话,很特殊,必须加 self。 the well-grounded rubyist p123. 有详细的介绍。 #14 楼 @aNdReW_Qx