Использование RABL с Draper для рендеринга to_json

У меня есть несколько довольно сложных ответов JSON в моем приложении для моей модели Ticket, и я бы хотел, чтобы мой TicketDecorator строил эти ответы.

Однако я уже настроил и API для своей системы и использую RABL для создания этих ответов JSON, поэтому я хотел бы повторно использовать уже созданные шаблоны.

Мне интересно, можно ли отобразить шаблон RABL из метода внутри TicketDecorator, примерно так:

Вот мой шаблон RABL tickets/show.json.rabl

object @ticket

attributes :id, :link, :reported_ago_in_words_with_reporter,
           :last_updated_in_words_with_updater, :priority_label, :status,
           :location, :category_list

node(:attachment_urls) { |ticket| [ asset_path(ticket.first_attachment_url),     asset_path(ticket.second_attachment_url), asset_path(ticket.third_attachment_url) ] }

node(:comment_count) { |ticket| ticket.comments.count }

child :recent_comments do
  extends 'comments/index'
end

и вот мой метод TicketDecorator:

class TicketDecorator < ApplicationDecorator
  def as_json
    h.render(template: "tickets/show", formats: :json)
  end
end

Однако это не работает, потому что я не могу успешно установить @ticket, и я получаю сообщение об ошибке: undefined method `first_attachment_url' for nil:NilClass, потому что @ticket равно нулю.

У кого-нибудь есть хорошие решения о том, как я могу заставить эти два работать вместе?

Моей единственной реальной мыслью будет рендеринг шаблона в строку и использование RABL вручную, но я не уверен, как я смогу вызвать render_to_string внутри Draper, поскольку это не помощник представления.

Есть мысли по этому поводу?


person TheDelChop    schedule 13.04.2012    source источник


Ответы (2)


Если речь идет о доступе к объектам в Rabl, возможно, это может вам помочь.

Также на ваших пользовательских узлах я бы обращался к объекту напрямую, вместо того, чтобы полагаться на переменную блока. Последний imo предназначен для обработки коллекций, например:

collection @tickets
  attribute :name
  node(:some_complex_stuff) {|ticket| ticket.vendor.heavy_lifting}

Вы также можете обратить внимание на тот факт, что вы можете вызывать любой метод объекта как атрибут, поскольку он все еще Ruby :)

class Ticket
  def we_got_what
    "the funk!"
  end
end

Для того, чтобы стать крутым в своем Рабле, просто сделайте:

object @ticket
 attribute :we_got_what
person dabai    schedule 16.06.2012

Теперь в вики rabl есть запись, описывающая подобную ситуацию. Для других прибывающих, проверьте это здесь

Решение состоит в том, чтобы отправить декоратор в rabl, а не рендерить rabl из декоратора. Перекладывание ответственности немного упрощает задачу.

person Dane O'Connor    schedule 15.04.2013