我正在尝试创建一个继承Array的Messages对象。消息将收集一组Message对象。我正在尝试使用ROXML创建一个xml输出,如下所示:
<messages>
<message>
<type></type>
<code></code>
<body></body>
</message>
...
</messages>
但是,我无法弄清楚如何让Messages对象中的消息对象显示在xml中。这是我一直在使用的代码:
require 'roxml'
class Message
include ROXML
xml_accessor :type
xml_accessor :code
xml_accessor :body
end
class Messages < Array
include ROXML
# I think this is the problem - but how do I tell ROXML that
# the messages are in this instance of array?
xml_accessor :messages, :as => [Message]
def add(message)
self << message
end
end
message = Message.new
message.type = "error"
message.code = "1234"
message.body = "This is a test message."
messages = Messages.new
messages.add message
puts messages.length
puts messages.to_xml
输出:
1
<messages/>
因此,我没有显示添加到消息中的消息对象。有人有主意吗?或者我是以错误的方式解决这个问题?
感谢您的帮助。
答案 0 :(得分:2)
我不认为你想要什么是可能的。您正试图访问Array
类的内部状态,这不仅是不可能的,因为在大多数实现中,这些内部隐藏在C / C ++ / Java / .NET / Objective-C / ABAP中运行时,但也只是一个坏主意和糟糕的面向对象设计。
问题是,Messages
实际上不是Array
,因此它不应该从Array
继承。告诉我:您真的100%确定您的Messages
课程能够忠实履行Array
上所有 81方法的合同吗?当应用于assoc
时,rassoc
,rindex
,transpose
和Messages
甚至是什么意思会怎样?
在这里使用委托而不是继承你会好得多。这为您提供了一个很好的命名实体,您可以将其传递给xml_accessor
:
require 'forwardable'
require 'roxml'
class Messages
extend Forwardable
include ROXML
class << self; alias_method :[], :new end
xml_reader :messages, :as => [Message]
def initialize(*messages) @messages = messages end
def_delegators :messages, :length, :<<
end
注意:我在这里也改变了其他一些事情。例如,我个人认为一个对象在构造之后应该是有效的和可用的。在您的代码版本中,Message
在构建后基本上无效,只有在您调用type=
,code=
和body=
setter后才有效:
class Message
include ROXML
class << self; alias_method :[], :new end
xml_reader :type, :body
xml_reader :code, :as => Integer
def initialize(type=nil, code=nil, body=nil)
@type, @code, @body = case opts = type
when Hash
opts[:type], opts[:code], opts[:body]
else
type, code, body
end
end
end
这是一个稍微扩展的用法示例:
msgs = Messages[Message['error', 1234, 'This is a test message.'], Message[]]
msgs << Message[
type: 'warning',
code: 4815162342,
body: 'This is another test message.'
]
puts msgs.to_xml
# => <messages>
# => <message>
# => <type>error</type>
# => <body>This is a test message.</body>
# => <code>1234</code>
# => </message>
# => <message/>
# => <message>
# => <type>warning</type>
# => <body>This is another test message.</body>
# => <code>4815162342</code>
# => </message>
# => </messages>