2012-04-13 27 views
5

Mam kilka dość skomplikowanych odpowiedzi JSON w mojej aplikacji dla mojego Ticket modelu i chciałbym mój TicketDecorator być tym, który buduje te odpowiedzi.Korzystanie Rabl z Draper do renderowania to_json

Jednak mam już setup i API dla mojego systemu i używam RABL do budowania tych odpowiedzi JSON, więc chciałbym ponownie użyć szablonów, które już utworzyłem.

Zastanawiam się, czy to możliwe, aby uczynić szablon Rabl od wewnątrz metody wewnątrz TicketDecorator, coś takiego:

Oto moja Rabl szablon 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 

i tu jest moja metoda TicketDecorator :

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

jednak to nie działa, ponieważ nie mogę z powodzeniem ustawić @ticket i dostaję ERR lub mówiąc: undefined method `first_attachment_url' for nil:NilClass ponieważ @ticket jest zerowe.

Ktoś ma jakieś dobre rozwiązania, w jaki sposób mogę sprawić, by te dwie prace były ładnie połączone?

Moja jedyna prawdziwa myśl to renderowanie szablonu do napisu i ręczne używanie RABL, ale nie jestem pewien, jak mógłbym wywołać render_to_string wewnątrz Drapera, ponieważ nie jest on pomocnikiem widoku.

Jakieś przemyślenia na ten temat?

Odpowiedz

1

Jeśli chodzi o dostęp do obiektów w Rabl, być może this może ci pomóc.

Również na Twoich niestandardowych węzłach chciałbym uzyskać bezpośredni dostęp do obiektu, zamiast polegać na zmiennej blokowej. Ten ostatni jest imo przeznaczona do obsługi zbiorów, tak:

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

Można również spojrzeć na fakt, że można wywołać dowolną metodę obiektu takiego atrybutu, ponieważ nadal jest Ruby :)

class Ticket 
    def we_got_what 
    "the funk!" 
    end 
end 

aby uzyskać ostry w swojej Rabl prostu zrobić:

object @ticket 
attribute :we_got_what 
0

jest teraz Rabl wpis wiki opisując takiej sytuacji. Dla innych przybywających, check it out here

Rozwiązaniem jest wysłanie dekoratora do routera zamiast renderowania go z dekoratora. Przerzucenie odpowiedzialności trochę ułatwia sprawę.

Powiązane problemy