to_xml在通过Rails返回的对象上不起作用ActiveRecord habtm参考 [英] to_xml Doesn't Work on Objects Returned Through Rails ActiveRecord habtm Reference
问题描述
我有两个rails活动记录类,分别是通过has_and_belongs_to_many关系链接的School和Instructor.
I have two rails active record classes, School and Instructor linked by a has_and_belongs_to_many relationship.
我需要查询我的教师学校特定学校的教师,并返回xml格式的响应.因此,在索引方法中,我有以下代码片段:
I need to query my instructors_controller for instructors for a particular school and return an xml format response. Therefore, in the index method I have this code fragment:
school = School.find(params[:school_id])
@instructors = school.instructors
及更高版本:
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @instructors }
format.json { render :json => @instructors }
end
但是它不起作用.看看这个有趣但令人困惑的序列:
But it doesn't work. Look at this intriguing but baffling sequence:
ruby-1.9.2-p180 :023 > Instructor.all.first
=> #<Instructor id: 1, name: "Mrs. Smith", instructor_type_id: 1, created_at: "2011-07-24 18:19:40", updated_at: "2011-07-24 18:19:40">
ruby-1.9.2-p180 :026 > Instructor.all.first.class
=> Instructor(id: integer, name: string, instructor_type_id: integer, created_at: datetime, updated_at: datetime)
ruby-1.9.2-p180 :024 > School.first.instructors.first
=> #<Instructor id: 1, name: "Mrs. Smith", instructor_type_id: 1, created_at: "2011-07-24 18:19:40", updated_at: "2011-07-24 18:19:40">
ruby-1.9.2-p180 :025 > School.first.instructors.first.class
=> Instructor(id: integer, name: string, instructor_type_id: integer, created_at: datetime, updated_at: datetime)
ruby-1.9.2-p180 :021 > Instructor.all.first.to_xml
=> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<instructor>\n <created-at type=\"datetime\">2011-07-24T18:19:40Z</created-at>\n <id type=\"integer\">1</id>\n <instructor-type-id type=\"integer\">1</instructor-type-id>\n <name>Mrs. Smith</name>\n <updated-at type=\"datetime\">2011-07-24T18:19:40Z</updated-at>\n</instructor>\n"
现在是重点:
ruby-1.9.2-p180 :019 > School.first.instructors.first.to_xml
NoMethodError: undefined method `type' for nil:NilClass
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activesupport-3.0.9/lib/active_support/whiny_nil.rb:48:in `method_missing'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activerecord-3.0.9/lib/active_record/serializers/xml_serializer.rb:230:in `compute_type'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:22:in `initialize'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:75:in `new'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:75:in `block in serializable_attributes'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `each'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `map'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `serializable_attributes'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:116:in `add_attributes_and_methods'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:103:in `block in serialize'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:134:in `call'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:134:in `_nested_structures'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:58:in `method_missing'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:31:in `tag!'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:102:in `serialize'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activerecord-3.0.9/lib/active_record/serializers/xml_serializer.rb:175:in `to_xml'
from (irb):19
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'ruby-1.9.2-p180 :020 > Instructor.all.first.to_xml
这是怎么回事?
好吧,尽管我仍然想知道上述行为的解释,但从xml切换到json解决了这个问题(to_json在这里与to_xml并不一样).
Well, switching from xml to json solved the problem, (to_json does not exhibit the same strangeness as to_xml here), although I would still like to know the explanation for the above behavior.
而且,由于我是Rails的新手,是否有更好的方法来做我想在这里做的事情?
Also, as I am relatively new to Rails, is there a better way to do what I want to do here ?
推荐答案
to_xml()尝试为每个模型属性定义一个type属性.例如,具有年龄(INT)属性的用户模型将具有:<age type="integer">42</age>
.此类型信息未使用JSON编码,这就是to_json()为您工作的原因.将此方法添加到您的讲师模型中:
to_xml() tries to define a type attribute for each model attribute. For example, a User model with an age (INT) attribute will have: <age type="integer">42</age>
. This type information is not encoded in JSON, which is why to_json() works for you. Add this method to your Instructor model:
def to_xml(options = {})
to_xml_opts = {:skip_types => true} # no type information, not such a great idea!
to_xml_opts.merge!(options.slice(:builder, :skip_instruct))
# a builder instance is provided when to_xml is called on a collection of instructors,
# in which case you would not want to have <?xml ...?> added to each item
to_xml_opts[:root] ||= "instructor"
self.attributes.to_xml(to_xml_opts)
end
但是,这将使您的XML缺少任何类型信息-如果某人拥有JAVA REST客户端,那就不好了.更好的策略是过滤self.attributes.slice(*keys).to_xml(to_xml_opts)
,其中 keys 是XML中所需的模型属性数组.
This would however make your XML devoid of any type information - not good if someone has a JAVA REST client. A better strategy would be to filter self.attributes.slice(*keys).to_xml(to_xml_opts)
where keys is an array of model attributes you want in the XML.
这篇关于to_xml在通过Rails返回的对象上不起作用ActiveRecord habtm参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!