2015-03-15 5 views
-1

У меня есть модель activerecord с некоторыми атрибутами, которые мне нужно переопределить при создании xml для API. Инструкции here, описывающие, как писать пользовательский метод to_xml, отлично подходят для этого.Переопределение ActiveRecord :: Base # to_xml для родителя, но не для детей

Проблема, с которой я сталкиваюсь, заключается в том, что модель находится на вершине довольно глубокой системы отношений, и это будет огромная работа, чтобы вручную указать генерацию xml всех потомков. Есть ли способ передать управление Builder для отношений, чтобы он мог автоматически создавать свой xml так же, как прежде, чем мне пришлось переопределить?

Вот пример того, что я хотел бы сделать:

class IHaveMyOwnXML < ActiveRecord::Base 
    has_many :widgets 
    def to_xml(options = {}) 
    options[:indent] ||= 2 
    xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) 
    xml.instruct! unless options[:skip_instruct] 
    xml.level_one do 
     xml.tag!(:second_level, 'content') 
    end 
    xml.pick_up_where_you_left_off! widgets 
    end 
end 

Очевидно pick_up_where_you_left_off! не существует. Я хочу, чтобы xml для widgets, который должен быть введен в этот момент в документе xml, выглядящий точно так, как если бы я не сделал переопределение, и вызвал IHaveMyOwnXML # to_xml (: include =>: widgets).

Возможно ли это? Или, как только вы переопределяете ActiveRecord # to_xml, выполняете ли вы затем вручную кодирование xml-продукции для произвольно глубоких вложенных отношений AR?

Я пробовал первое предложенное предложение, и, хотя оно само по себе, я не могу сказать, как вводить отношение, когда я вхожу в свой собственный метод to_xml. ни один из следующих работ:

xml.household do 
    xml.id id 
    xml.accounts accounts 
end 

xml.household do 
    xml.id id 
    xml << accounts.to_xml # also w/ (opts.merge(:builder => xml)) 
end 

Первый раз не дает объект рубин реф (<accounts>#&lt;Account:0x10abb5250&gt;</accounts>). Второй вводит полный XML-документ с узлом household в качестве корня и объявлением xml.

ответ

0

Я думаю, что вы можете достичь этого, делая что-то вроде этого:

Вы определяете метод, который отвечает, если модель хочет Пользовательские XML

# Parent 
def use_custom_xml? 
    true 
end 

# Child 
def use_custom_xml? 
    false 
end 

Теперь вы можете написать свой собственный генератор XML на родителе вот так:

def to_xml(options = {}) 
    return super unless use_custom_xml? 
    # ... your custom code 
end 

Я не пробовал это для генерации xml, но использовал аналогичный шаблон, и он работал для меня.

+0

Спасибо. Первоначальное тестирование, похоже, указывает на то, что это сработает. Я уже пробовал это, но он путался с начальными аргументами, отправленными на верхнем уровне - 'foo.to_xml (: include => {: bar =>: car})' - это получало исключение, потому что Bar doesn ' t 'has_any: bars'. Рассмотрев ваш ответ, я понял, что я не должен использовать: include, когда я определяю to_xml вручную b/c. Я уже явно делаю 'xml.bar bar' – Avram

+0

Хорошо, получается, что хотя это нормально, это неполный. Я не могу понять, как вставить отношение в xml, как только use_custom_xml? True. Я обновил вопрос с дополнительной задачей. – Avram

Смежные вопросы