我看到一些与分配相关的ActiveRecord真正奇怪的行为。 我有一个名为 Venue 的 ActiveRecord 模型,其中包括 Venue 的测量值,所有整数都小于 1K。我们通过 XML 源添加场馆。在模型本身上,我有一个Venue.from_xml_feed
方法获取XML,解析并创建场地。
问题来自测量。 使用 Nokogiri
,我正在解析这样的测量值:
elems = xml.xpath("//*[@id]")
elems.each do |node|
distance = node.css("distances")
rs = distance.attr("rs")
// get the rest of the sides
# using new instead of create to print right_side, behavior is the same
venue = Venue.new right_side: rs # etc
venue.save
puts venue.right_side
end
问题是venue.right_side
总是计算为nil
,即使distance.attr("rs")
包含合法值,比如 400。所以这段代码:
rs = distance.attr("rs")
puts rs
Venue.new right_side: rs
将打印400
,然后将 rs 另存为 nil。 如果我尝试任何类型的类型转换,如下所示:
content = distance.attr("rs").content
str = content.to_s
int = Integer(str)
puts "Is int and Integer? #{int.is_a? Integer}"
Venue.new right_side: int
它将打印Is int an Integer? true
,然后再次保存Venue.right_side
另存为nil
。
但是,如果我只是显式创建一个随机整数,如下所示:
int = 400
Venue.new right_side: int
它将Venue.right_side
保存为400
. 谁能告诉我这是怎么回事?
好吧,您未能包含先决条件示例 XML 来确认这一点,因此您得到了一个相当通用的答案。
在代码中使用:
distance = node.css("distances")
rs = distance.attr("rs")
css
不会返回您认为它所做的事情。它返回一个类似于数组的 NodeSet。当您尝试在 NodeSet 上使用attr
时,您将设置值,而不是检索它。从文档中:
#attr(key, value = nil, &blk) ⇒ Object (also: #set, #attribute)
在节点集中的所有节点对象上将属性键设置为值或 blk 的返回值。
由于您没有使用值,因此生成的操作是从标记中删除该属性,然后返回 nil,Ruby 会将 nil 分配给rs
。
如果要获取节点的属性,则需要指向节点本身,因此请使用at
或at_css
,其中任何一个都返回节点。拥有节点后,可以使用attribute
检索值,或使用类似于以下未经测试的代码的[]
快捷方式:
rs = node.at('distances')['rs']
同样,由于您没有提供 XML,因此无法判断您可能还尝试执行哪些操作,或者此代码是否完全准确。