ruby-on-rails - to_xml 不适用于通过 Rails ActiveRecord habtm 引用返回的对象

标签 ruby-on-rails xml reference has-and-belongs-to-many

我有两个 Rails 事件记录类,School 和 Instructor 通过 has_and_belongs_to_many 关系链接。

我需要在我的 instructors_controller 中查询特定学校的讲师并返回 xml 格式的响应。因此,在索引方法中我有这个代码片段:

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

但它不起作用。看看这个有趣但令人费解的序列:

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 相同的奇怪之处),尽管我仍然想知道对上述行为的解释。

此外,由于我对 Rails 比较陌生,是否有更好的方法来完成我想在这里做的事情?

最佳答案

to_xml() 尝试为每个模型属性定义一个类型属性。例如,具有年龄 (INT) 属性的用户模型将具有:<age type="integer">42</age> .此类型信息未以 JSON 编码,这就是 to_json() 适合您的原因。将此方法添加到您的 Instructor 模型中:

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 中包含的模型属性数组。

关于ruby-on-rails - to_xml 不适用于通过 Rails ActiveRecord habtm 引用返回的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6808958/

相关文章:

c# - 使用 LINQ 将 XML 数据插入现有 XML

c# - 引用名称大小写不符合 CLS

pointers - Rust 中 &4 等文字引用的所有者是什么?

javascript - 如何引用任何给定行的表格单元格内的一组复选框

ruby-on-rails - as_json 没有在关联上调用 as_json

ruby-on-rails - 无法加载 `Rails.application.database_configuration` : (NoMethodError) with launching to Heroku

ruby-on-rails - Opsworks Rails 控制台环境

ruby-on-rails - 如何使用设计 : rememberable?

java - 从 XML 文档获取节点

android - 画廊 Activity 崩溃了吗?