to_xml include не работает в rails 3.0.6 ruby ​​1.9.2 - PullRequest
1 голос
/ 14 апреля 2011

Я обновил свой сервер до ruby ​​1.9.2, и он перестал работать (rails 3.0.6):

def index  
  @musicians = Musician.includes(:instruments)
  render :xml => @musicians.to_xml( :include => :instruments )
end

И модели:

class Musician < ActiveRecord::Base
  has_and_belongs_to_many :instruments
end

class Instrument < ActiveRecord::Base
  has_and_belongs_to_many :musicians
end

ЯПолучение этой ошибки:

undefined method `type' for nil:NilClass

Трассировка фреймворка:

activesupport (3.0.6) lib/active_support/whiny_nil.rb:48:in `method_missing'
activerecord (3.0.6) lib/active_record/serializers/xml_serializer.rb:230:in `compute_type'
activemodel (3.0.6) lib/active_model/serializers/xml.rb:22:in `initialize'
activemodel (3.0.6) lib/active_model/serializers/xml.rb:75:in `new'
activemodel (3.0.6) lib/active_model/serializers/xml.rb:75:in `block in serializable_attributes'

Любая подсказка, что я делаю неправильно?

Может быть, это связано с: https://rails.lighthouseapp.com/projects/8994/tickets/4840-to_xml-doesnt-work-in-such-case-eventselecttitle-as-tto_xml

Ответы [ 3 ]

4 голосов
/ 21 апреля 2011

Это основная проблема с Rails.Происходит следующее: когда включаются инструменты, добавляется атрибут instrument_id.Затем, когда каждый инструмент сериализуется, класс XmlSerializer определяет тип этого атрибута на основе определения класса инструмента, используя атрибут type для каждого столбца.Поскольку атрибут instrument_id не существует в определении класса, возвращается объект nil, который, начиная с Ruby 1.9, не имеет атрибута type, от которого зависит Rails.

(Я не думаю, что исправление в теме, на которую вы ссылаетесь, работает, но то, что я привел ниже, работает.)

Есть два способа исправить это:

  1. Не сериализуйте instrument_id (хорошая идея).
    render :xml => @musicians.to_xml( :include => { :instruments => { :except => :instrument_id } } )
  2. Или исправление ядра Rails (плохая идея).
    --- a/activerecord/lib/active_record/serializers/xml_serializer.rb  2011-04-20 15:01:10.000000000 -0700
    +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb      2011-04-20 15:00:42.000000000 -0700
    @@ -226,8 +226,10 @@
    
         class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
           def compute_type
    +        Rails.logger.info("key: #{name}, hash: #{@serializable.class.columns_hash[name]}")
             type = @serializable.class.serialized_attributes.has_key?(name) ?
    -          super : @serializable.class.columns_hash[name].type
    +          super : @serializable.class.columns_hash[name].nil? ?
    +            NilClass : @serializable.class.columns_hash[name].type
    
             case type
             when :text
0 голосов
/ 23 сентября 2011

Вот обходной путь, который помог мне.

Я преобразовал все активные объекты записи в хэши с помощью вызова атрибутов, который устранил проблему для меня

@ musicians = @musicians.map {| |a.attributes}

@musicians.to_xml

0 голосов
/ 14 апреля 2011

Полагаю, если вы используете HABTM ассоциацию, у вас должна быть таблица соединения с именем musicians_instruments, вы должны также включить эту вложенную.

render :xml => @musicians.to_xml( :include => {:musicians_instruments =>{:include=>:instruments}} )

Обратите внимание, что включение отличается от ActiveRecord ассоциаций.

Обновление

Если вы создаете модель для таблицы соединений, вы можете изменить has_and_belongs_to_many на has_many :through, он используется чаще и делает то же самое.

#musician.rb
has_many :musicians_instruments
has_many :instruments, :through=>:musicians_instruments

#instrument.rb
has_many :musicians_instruments
has_many :musicians, :through=>:musicians_instruments

Этот должен работать правильно с вложенными включениями to_xml.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...