为什么 ruby/rails/activerecord 中并不总是需要 self ?
在测试 Rails 模型中的 getter/setter 对时,我发现了一个我一直认为奇怪且不一致的行为的好例子。
在此示例中,我正在处理 class Folder < ActiveRecord::Base
。
文件夹属于:父级,:class_name => 'Folder'
在 getter 方法上,如果我使用:
def parent_name
parent.name
end
...或...
def parent_name
self.parent.name
end
...结果完全相同,我得到父文件夹的名称。但是,在 getter 方法中,如果我使用...
def parent_name=(name)
parent = self.class.find_by_name(name)
end
...parent 变为 nil,但如果我使用......
def parent_name=(name)
self.parent = self.class.find_by_name(name)
end
那么它就可以工作。
所以,我的问题是,为什么有时需要声明 self.method 以及为什么可以只使用局部变量?
ActiveRecord 中 self
的需要/使用似乎不一致,我想更好地理解这一点,所以我不觉得我总是在猜测是否需要声明 self 。什么时候你应该/不应该在 ActiveRecord 模型中使用 self ?
In testing a getter/setter pair in a rails model, I've found a good example of behavior I've always thought was odd and inconsistent.
In this example I'm dealing with class Folder < ActiveRecord::Base
.
Folder belongs_to :parent, :class_name => 'Folder'
On the getter method, if I use:
def parent_name
parent.name
end
...or...
def parent_name
self.parent.name
end
...the result is exactly the same, I get the name of the parent folder. However, in the getter method if I use...
def parent_name=(name)
parent = self.class.find_by_name(name)
end
... parent becomes nil, but if I use...
def parent_name=(name)
self.parent = self.class.find_by_name(name)
end
...then then it works.
So, my question is, why do you need to declare self.method sometimes and why can you just use a local variable?
It seems the need for / use of self
in ActiveRecord is inconsistent, and I'd like to understand this better so I don't feel like I'm always guessing whether I need to declare self or not. When should you / should you not use self in ActiveRecord models?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为属性/关联实际上是方法(getters/setters)而不是局部变量。当您声明“parent = value”时,Ruby 假定您要将值分配给局部变量parent。
在堆栈的某个位置,有一个 setter 方法“defparent=”,要调用该方法,您必须使用“self.parent=”来告诉 ruby 您实际上想要调用 setter,而不仅仅是设置局部变量。
当谈到 getter 时,Ruby 首先查看是否存在局部变量,如果找不到它,那么它会尝试查找具有相同名称的方法,这就是为什么 getter 方法在没有“self”的情况下也能工作。
换句话说,这不是 Rails 的错,而是 Ruby 固有的工作方式造成的。
This is because attributes/associations are actually methods(getters/setters) and not local variables. When you state "parent = value" Ruby assumes you want to assign the value to the local variable parent.
Somewhere up the stack there's a setter method "def parent=" and to call that you must use "self.parent = " to tell ruby that you actually want to call a setter and not just set a local variable.
When it comes to getters Ruby looks to see if there's a local variable first and if can't find it then it tries to find a method with the same name which is why your getter method works without "self".
In other words it's not the fault of Rails, but it's how Ruby works inherently.