在Michael Hartl的教程中,他有一个module SessionsHelper
,它有一个名为current_user=
的方法,它接受一个参数并将其分配给@current_user
。然后,他使用类似current_user = User.first
的行在其程序中使用各种其他方法调用此方法。
我的问题是我们如何知道current_user=
方法被调用 - 在我看来,实际发生的是一个名为current_user
的新变量是在现场创建的,给定User.first
的值,然后当函数关闭该变量时,
我还通过创建以下代码来测试它:
def x= val
puts "method called"
end
x = 46
puts x
此代码段只是在屏幕上打印46 - 根本不会调用函数x=
。那么current_user=
方法在Michael Hartl的教程中做了什么,以及他如何调用该函数?
答案 0 :(得分:4)
这是因为Ruby会将可以作为简单变量读取的表达式视为简单变量。您可以使用以下代码查看它:
def x
10
end
print x #=> 10
x = 5
print x #=> 5
print x() #=> 10
print self.x #=> 10
这是同样的情况。看:
def x=(a)
print a
end
x = 8 #=> Variable 'x' assigned to 8
x=(8) #=> The same
self.x = 8 #=> Function called
还记得赋值函数(比如最后一个)不能返回任何值,返回值总是最后一个参数。
def x=(a)
return a+1
end
var = (self.x = 8) #=> Function called; Variable 'var' assigned to 8
答案 1 :(得分:0)
Rubyists的一个常见抱怨是,当你提到变量或方法时,有时很难说出来。这是尝试使用我公认的有限理解来解释它是如何工作的。
Ruby没有“对象属性”的概念,至少与大多数其他语言不同。如果你的对象有一个名为@current_user的实例变量,那么该对象之外的任何东西都是完全无法访问的(instance_variable_get和instance_variable_set除外 - 这里有龙。)唯一的方式从外面获取或设置@current_user是定义“current_user”和/或“current_user =”方法(或“attr_accessor:current_user”,它们做同样的事情。)
因此,当您调用“obj.current_user = user”时,会调用一些语法糖,并且Ruby知道您只是调用current_user =方法。毕竟,由于您无法在外部访问实例变量,因此根本没有其他任何意义。
当你在对象内部时,需要使用“self.current_user = user”调用current_user =。否则你是对的,它只会创建一个局部变量。由于Ruby在其OO设计中非常一致,这正是您的示例中正在发生的事情。 “x = 5”只是创建一个局部变量,但“self.x = 5”会调用x =方法。
答案 2 :(得分:0)
注意:正如其他答案所示,x =和self.x =执行不同的功能。
在SessionsHelper的范围内,我认为通常的用法是将该模块用作类的mixin。
请考虑以下事项:
class Foo
include SessionsHelper
def foo_current_user
puts 'foo' + current_user
end
end
class Bar
include SessionsHelper
def bar_current_user
puts 'bar' + current_user
end
end
因此,他的模块允许您在遵守DRY原则的同时执行Foo.new.foo_current_user()
和Bar.new.bar_current_user()
。
它将值存储到两个类中的实例变量@current_user中。在课堂之外,mixin模块可能没有多大意义。