Rails ActiveAttr Gem,在 Class 内操纵属性?
Rails ActiveAttr Gem, manipulation of attributes within Class?
我有一个 Rails 5 class,其中包括 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(...)
被定义得更远,它起作用并且它的 return值正确)。我发现设置此变量的唯一方法是改写 self.productontology
。而且,实例变量@uri
没有定义为属性,而是只写在这个地方,对外可见。
可能我只是忘记了 Ruby 和 Rails 的基础知识,我已经用 ActiveRecord 和 ActiveModel 做了这么长时间。任何人都可以解释为什么我需要写 self.productontology
,使用 @productontology
不起作用,以及为什么我写原始代码的前辈将 @uri
中的 @ 符号与属性声明样式混合在一起?我想他一定是有什么理由这样做的。
我也对任何指向文档的指示感到满意。我一直无法找到 ActiveAttr 的文档,其中显示了在 ActiveAttr class.
方法中对实例变量的操作
谢谢:-)
首先,您很可能不需要 ActiveAttr gem,因为它实际上只是复制已经 available in Rails 5.
的 API
参见https://api.rubyonrails.org/classes/ActiveModel.html。
As I have written it, the method fetch_po_field does not work, it thinks that productontology is a local variable.
这实际上只是一个 Ruby 问题,与 Rails 属性 API 或 ActiveAttr gem.
无关
使用赋值时,您必须显式设置接收者,除非您想设置局部变量。这一行:
self.productontology = g_i_f_n('ontology') if identifier
实际上是在 self 上使用 rval 作为参数调用 setter 方法 productontology=
。
Can anybody explain why I need to write self.productontology, using
@productontology doesn't work
考虑这个普通的旧 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 实例方法以及一些关于属性的元数据,如它的“类型”、默认值等。存储在 class.
我有一个 Rails 5 class,其中包括 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(...)
被定义得更远,它起作用并且它的 return值正确)。我发现设置此变量的唯一方法是改写 self.productontology
。而且,实例变量@uri
没有定义为属性,而是只写在这个地方,对外可见。
可能我只是忘记了 Ruby 和 Rails 的基础知识,我已经用 ActiveRecord 和 ActiveModel 做了这么长时间。任何人都可以解释为什么我需要写 self.productontology
,使用 @productontology
不起作用,以及为什么我写原始代码的前辈将 @uri
中的 @ 符号与属性声明样式混合在一起?我想他一定是有什么理由这样做的。
我也对任何指向文档的指示感到满意。我一直无法找到 ActiveAttr 的文档,其中显示了在 ActiveAttr class.
方法中对实例变量的操作谢谢:-)
首先,您很可能不需要 ActiveAttr gem,因为它实际上只是复制已经 available in Rails 5.
的 API参见https://api.rubyonrails.org/classes/ActiveModel.html。
As I have written it, the method fetch_po_field does not work, it thinks that productontology is a local variable.
这实际上只是一个 Ruby 问题,与 Rails 属性 API 或 ActiveAttr gem.
无关使用赋值时,您必须显式设置接收者,除非您想设置局部变量。这一行:
self.productontology = g_i_f_n('ontology') if identifier
实际上是在 self 上使用 rval 作为参数调用 setter 方法 productontology=
。
Can anybody explain why I need to write self.productontology, using @productontology doesn't work
考虑这个普通的旧 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 实例方法以及一些关于属性的元数据,如它的“类型”、默认值等。存储在 class.