[英]Rails - attr_accessor :- read the attribute value instead of the function overriding it
I have a model Customer
that accepts a virtual attribute opening_balance
.我有一个接受虚拟属性opening_balance
的模型Customer
。 Code looks something like this:代码如下所示:
model Customer < ApplicationRecord
attr_accessor :opening_balance
has_one :ledger_account
after_create :open_ledger_account
def opening_balance
ledger_account.opening_balance if ledger_account.present?
end
private
def open_ledger_account
create_ledger_account!(opening_balance: self.opening_balance)
end
But the issue here is self.opening_balance
is calling the method defined in the class not the value stored in attr_accessor's opening_balance attribute.但这里的问题是self.opening_balance
调用的是类中定义的方法,而不是存储在 attr_accessor 的 opening_balance 属性中的值。
I tried one more solution:我尝试了另一种解决方案:
def open_ledger_account
create_ledger_account!(opening_balance: self.read_attribute(:opening_balance))
end
But this also doesn't work.但这也行不通。
How to read the value stored in the actual attribute?如何读取存储在实际属性中的值? Any help would be appreciated.任何帮助,将不胜感激。 I am using rails 5.1.我正在使用导轨 5.1。
Thanks!谢谢!
attr_accessor
defines a instance variable and a method to access it (read/write). attr_accessor
定义了一个实例变量和一个访问它的方法(读/写)。
So the easy way is to write:所以最简单的方法是写:
def open_ledger_account
create_ledger_account!(opening_balance: @opening_balance)
end
The read_attribute
would only work if opening_balance
was an attribute in the database on Customer
. read_attribute
只有在opening_balance
是Customer
数据库中的一个属性时才有效。
First you have to understand that attr_accessor
does not define instance variables.首先你要明白attr_accessor
没有定义实例变量。 It just creates setter and getter methods.它只是创建 setter 和 getter 方法。 What attr_accessor :name
does is: attr_accessor :name
作用是:
class Person
def name
@name
end
def name=(value)
@name = value
end
end
Now you can access the instance variable from the outside:现在您可以从外部访问实例变量:
p = Person.new
p.name = 'Jane'
puts p.name
And you can also access the instance variable from the inside by using the getter method instead of @name
:您还可以使用 getter 方法而不是@name
从内部访问实例变量:
class Person
attr_accessor :name
def hello
"hello my name is: #{name}"
end
end
attr_accessor
does not "define" a instance variable. attr_accessor
不“定义”实例变量。 There is no declaration of members/attributes in Ruby like in for example Java. Ruby 中没有成员/属性的声明,例如在 Java 中。 An instance variables is declared when it is first set.实例变量在第一次设置时声明。 Accessing an instance variable that has not been assigned a value returns nil.访问尚未赋值的实例变量返回 nil。
So whats happing here:那么这里发生了什么:
class Customer < ApplicationRecord
attr_accessor :opening_balance
# ...
def opening_balance
ledger_account.opening_balance if ledger_account.present?
end
end
Is that you are overwriting the getter created by attr_accessor
.是你覆盖了attr_accessor
创建的attr_accessor
。 If you want to access the instance variable itself just use @opening_balance
.如果您想访问实例变量本身,只需使用@opening_balance
。
You should just use delegate instead:您应该只使用委托:
class Customer < ApplicationRecord
has_one :ledger_account
delegate :opening_balance, to: :ledger_account
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.