Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using RABL with Draper to render to_json

I've got some fairly complex JSON responses in my application for my Ticket model and I'd like my TicketDecorator to be the one who builds those responses.

However, I've already setup and API for my system and use RABL to build those JSON responses, so I'd like to reuse the templates that I've already created.

I'm wondering if it's possible to render a RABL template from within a method inside TicketDecorator, something like this:

Here is my RABL template 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

and here is my TicketDecorator method:

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

However, this doesn't work because I can't sucessfully set @ticket, and I get an error saying: undefined method `first_attachment_url' for nil:NilClass because @ticket is nil.

Anybody have any good solutions on how I can make these two work nicely together?

My only real thought would be rendering the template to a string and using RABL manually, but I'm not sure how I'd be able to call render_to_string inside of Draper since its not a view helper.

Any thoughts about that?

like image 361
TheDelChop Avatar asked Nov 13 '22 07:11

TheDelChop


1 Answers

If it is a matter of accessing objects in Rabl, maybe this can be of help to you.

Also on your custom nodes I would access the object directly, instead of relying on the block variable. The latter is imo meant for handling collections, like this:

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

You might also look into the fact, that you can call any object method like an attribute since it still is Ruby :)

class Ticket
  def we_got_what
    "the funk!"
  end
end

In order to get funky in your Rabl just do:

object @ticket
 attribute :we_got_what
like image 127
Benjamin Avatar answered Dec 05 '22 14:12

Benjamin