我有一个Rails 5类,它包括ActiveAttr::Model、ActiveAttr:MassAssignment和ActiveAttr:::AttributeDefaults。
它使用方法attribute
定义了几个属性,并具有一些实例方法。我在操作已定义的属性时遇到了一些问题。我的问题是如何在初始值设定项中设置属性值。部分代码:
class CompanyPresenter
include ActiveAttr::Model
include ActiveAttr::MassAssignment
include ActiveAttr::AttributeDefaults
attribute :identifier
# ...
attribute :street_address
attribute :postal_code
attribute :city
attribute :country
# ...
attribute :logo
attribute :schema_org_identifier
attribute :productontology
attribute :website
def initialize(attributes = nil, options = {})
super
fetch_po_field
end
def fetch_po_field
productontology = g_i_f_n('ontology') if identifier
end
def uri
@uri ||= URI.parse(website)
end
# ...
end
正如我所写的,方法fetch_po_field
不起作用,它认为productontology是一个局部变量(g_i_f_n(...)
定义得更远,它起作用,并且它的返回值是正确的(。我发现设置这个变量的唯一方法是编写self.productontology
。此外,实例变量@uri
并没有被定义为属性,而是只写在这个地方,并且从外部可见。
也许我只是忘记了Ruby和Rails的基础知识,我已经用ActiveRecord和ActiveModel做了这么长时间了。有人能解释为什么我需要编写self.productontology
,而使用@productontology
不起作用吗?为什么我的前任编写了原始代码,并将@uri
中的@符号与属性声明样式混合在一起?我想他这样做一定是有原因的。
我也对任何指向文档的指针感到满意。我还没有找到ActiveAttr的文档,其中显示了在ActiveAttr类的方法中对实例变量的操作。
谢谢:-(
首先,您很可能不需要ActiveAttr-gem,因为它实际上只是复制了Rails5中已经可用的API。
请参阅https://api.rubyonrails.org/classes/ActiveModel.html.
正如我所写的,方法fetch_po_field不起作用,它认为productontology是一个局部变量。
这实际上只是Ruby的事情,与Rails Attributes API或ActiveAttr gem无关。
使用赋值时,除非要设置局部变量,否则必须显式设置收件人。此行:
self.productontology = g_i_f_n('ontology') if identifier
实际上是使用rval作为参数在self上调用setter方法productontology=
。
有人能解释为什么我需要写self.productontology吗@产品本体不起作用
考虑一下这个普通的老ruby示例:
class Thing
def initialize(**attrs)
@storage = attrs
end
def foo
@storage[:foo]
end
def foo=(value)
@storage[:foo] = value
end
end
irb(main):020:0> Thing.new(foo: "bar").foo
=> "bar"
irb(main):021:0> Thing.new(foo: "bar").instance_variable_get("@foo")
=> nil
这看起来与使用attr_accessor
创建的标准访问器有很大不同。代替存储";属性";在每个属性的一个实例变量中,我们使用散列作为内部存储,并创建访问者来公开存储的值。
Rails属性API做了完全相同的事情,除了它不仅仅是一个简单的散列,而且访问器是用元编程定义的。为什么?因为Ruby不允许您跟踪对简单实例变量的更改。如果设置@foo = "bar"
,则模型无法跟踪对属性的更改或执行类型转换之类的操作。
当您使用attribute :identifier
时,您正在编写setter和getter实例方法,以及一些关于属性的元数据,如它的";类型";,默认值等存储在类中。