为什么我不能在 Active Record 回调中直接访问实例变量?
Why can't I directly access instance variables in Active Record callback?
在 Active Record 回调中,我总是看到 examples using self.variable
. Sometimes, the self.
prefix isn't needed, so they use just variable
(see this related question).
根据我的阅读,这两种引用 class 实例变量的方法使用访问函数,而 @variable
将直接访问该变量。在我的代码中,我尝试使用 @variable
但它不起作用 - 就好像 @variable
尚未定义......你不能直接在 Active Record 回调中访问实例变量吗?
此外,我还没有为这个特定变量定义访问器函数,所以当我说 self.variable
或 variable
时实际发生了什么(我都试过了,两者都可以工作作业的 LHS)?
This question 本质上是我要问的,但我不明白答案并希望得到更多说明(我无法对答案发表评论,因为我是 Stack Overflow 的新手)。他的回答是这样的:
It [password] is the same as self.password. ActiveRecord defines methods, not instance variables to access stuff related to the database. That's why you cannot access it with @password.
但是我看到的回调方法总是在模型的 class 中定义的,这应该使它们能够访问实例变量,对吧?他还这样说:
PS: Callbacks are only method calls on your object. The only difference is that Rails calls them for you, not yourself.
那么他的意思是回调方法不是从对对象的引用中调用的吗?例如。而不是调用 model_instance.callback_method
,它只是调用 callback_method
?如果 callback_method 是一个 class 实例方法,那么如何在不引用 class 实例的情况下找到它?即使它确实以这种方式工作,它怎么知道 self.variable
是什么?
我相信你不太明白 Rails 属性不存储在实例变量中。您的所有属性(由数据库 table 模式定义)都存储在一个实例变量 @attributes
中,永远不会直接访问它,因为它是 Rails 实现细节的一部分.
示例:
class Thing < ActiveRecord::Base
# assume that we have a 'name' column in the database
def foo
# correct ways to access the name
name
self.name
self[:name]
# this contains name value and other name metadata
# but you shouldn't use it
@attributes[:name]
# this holds nil as that variable has no relation to the "name" attribute
@name
end
end
在回调中,它的工作方式与在所有其他方法中的工作方式相同 — 您可以访问您定义的实例变量,但不能将数据库属性作为实例变量访问。
class Thing < ActiveRecord::Base
attr_accessor :secret
after_initialize do
@secret = '123'
end
before_create do
p @secret
end
after_validation :on_validation
def on_validation
p @secret
end
end
如果您尝试创建一个 Thing
对象,基于块的 before_create
回调和基于方法的 after_validation
回调都可以访问 @secret
定义的实例变量在 after_initialize
回调中。
can you not access instance variables directly in an Active Record callback?
您可以从任何实例方法访问实例变量,包括用作 ActiveRecord 回调的实例变量。
Also, I haven't defined an accessor function for this particular variable, so what actually happens when I say self.variable or variable (I've tried both, and both work aside from the LHS of an assignment)?
首先,了解这两种语法之间的区别很重要。 variable = 123
会将值 123
分配给局部变量。 self.variable = 123
将在 self 上调用名为 variable=
的方法并将 123
作为参数传递。
> class Foo
> def x=(value)
> puts "Foo#x called with #{ value }"
> end
>
> def bar
> x = 123 # local variable assignment, `x` only exists inside the `bar` method.
> self.x = 456 # calls `x=`
> end
> end
> Foo.new.bar
Foo#x called with 456
可能有点令人困惑的是,使用隐式接收器调用的方法与引用局部变量共享相同的语法。
> class Bar
> def x
> "In method x"
> end
>
> def foo
> # No local variable `x` has been initialized yet, so references to `x` will call the method with that name.
> puts x # calls method `x` and prints "In method x".
> # This example is equivalent to `puts self.x`.
>
> x = "Hello" # Now that a local variable is defined it will hide the method `x`.
> puts x # references the local variable and prints "Hello".
> puts self.x # calls the method `x` and prints "In method x".
> end
> end
> Bar.new.foo
In method x
Hello
In method x
其次,您需要知道 ActiveRecord 为模型的每一列创建访问器方法 table。假设我有一个模型 User(id: integer, name: string, age: integer)
。 ActiveRecord 会定义 实例方法 id
, name
和 age
来读取属性和 id=
, name=
和 age=
设置属性。
实例变量完全是另一回事。您不能 使用 @id
、@name
、@age
等实例变量访问数据库属性。
So does he maybe mean that the callback methods aren't call from a reference to the object?
不,ActiveRecord 回调确实会调用对象的实例方法。
在 Active Record 回调中,我总是看到 examples using self.variable
. Sometimes, the self.
prefix isn't needed, so they use just variable
(see this related question).
根据我的阅读,这两种引用 class 实例变量的方法使用访问函数,而 @variable
将直接访问该变量。在我的代码中,我尝试使用 @variable
但它不起作用 - 就好像 @variable
尚未定义......你不能直接在 Active Record 回调中访问实例变量吗?
此外,我还没有为这个特定变量定义访问器函数,所以当我说 self.variable
或 variable
时实际发生了什么(我都试过了,两者都可以工作作业的 LHS)?
This question 本质上是我要问的,但我不明白答案并希望得到更多说明(我无法对答案发表评论,因为我是 Stack Overflow 的新手)。他的回答是这样的:
It [password] is the same as self.password. ActiveRecord defines methods, not instance variables to access stuff related to the database. That's why you cannot access it with @password.
但是我看到的回调方法总是在模型的 class 中定义的,这应该使它们能够访问实例变量,对吧?他还这样说:
PS: Callbacks are only method calls on your object. The only difference is that Rails calls them for you, not yourself.
那么他的意思是回调方法不是从对对象的引用中调用的吗?例如。而不是调用 model_instance.callback_method
,它只是调用 callback_method
?如果 callback_method 是一个 class 实例方法,那么如何在不引用 class 实例的情况下找到它?即使它确实以这种方式工作,它怎么知道 self.variable
是什么?
我相信你不太明白 Rails 属性不存储在实例变量中。您的所有属性(由数据库 table 模式定义)都存储在一个实例变量 @attributes
中,永远不会直接访问它,因为它是 Rails 实现细节的一部分.
示例:
class Thing < ActiveRecord::Base
# assume that we have a 'name' column in the database
def foo
# correct ways to access the name
name
self.name
self[:name]
# this contains name value and other name metadata
# but you shouldn't use it
@attributes[:name]
# this holds nil as that variable has no relation to the "name" attribute
@name
end
end
在回调中,它的工作方式与在所有其他方法中的工作方式相同 — 您可以访问您定义的实例变量,但不能将数据库属性作为实例变量访问。
class Thing < ActiveRecord::Base
attr_accessor :secret
after_initialize do
@secret = '123'
end
before_create do
p @secret
end
after_validation :on_validation
def on_validation
p @secret
end
end
如果您尝试创建一个 Thing
对象,基于块的 before_create
回调和基于方法的 after_validation
回调都可以访问 @secret
定义的实例变量在 after_initialize
回调中。
can you not access instance variables directly in an Active Record callback?
您可以从任何实例方法访问实例变量,包括用作 ActiveRecord 回调的实例变量。
Also, I haven't defined an accessor function for this particular variable, so what actually happens when I say self.variable or variable (I've tried both, and both work aside from the LHS of an assignment)?
首先,了解这两种语法之间的区别很重要。 variable = 123
会将值 123
分配给局部变量。 self.variable = 123
将在 self 上调用名为 variable=
的方法并将 123
作为参数传递。
> class Foo
> def x=(value)
> puts "Foo#x called with #{ value }"
> end
>
> def bar
> x = 123 # local variable assignment, `x` only exists inside the `bar` method.
> self.x = 456 # calls `x=`
> end
> end
> Foo.new.bar
Foo#x called with 456
可能有点令人困惑的是,使用隐式接收器调用的方法与引用局部变量共享相同的语法。
> class Bar
> def x
> "In method x"
> end
>
> def foo
> # No local variable `x` has been initialized yet, so references to `x` will call the method with that name.
> puts x # calls method `x` and prints "In method x".
> # This example is equivalent to `puts self.x`.
>
> x = "Hello" # Now that a local variable is defined it will hide the method `x`.
> puts x # references the local variable and prints "Hello".
> puts self.x # calls the method `x` and prints "In method x".
> end
> end
> Bar.new.foo
In method x
Hello
In method x
其次,您需要知道 ActiveRecord 为模型的每一列创建访问器方法 table。假设我有一个模型 User(id: integer, name: string, age: integer)
。 ActiveRecord 会定义 实例方法 id
, name
和 age
来读取属性和 id=
, name=
和 age=
设置属性。
实例变量完全是另一回事。您不能 使用 @id
、@name
、@age
等实例变量访问数据库属性。
So does he maybe mean that the callback methods aren't call from a reference to the object?
不,ActiveRecord 回调确实会调用对象的实例方法。