drapergem / draper

Decorators/View-Models for Rails Applications
MIT License
5.22k stars 527 forks source link

Usage with `Turbo::Broadcastable` #910

Closed Alexey1100 closed 1 week ago

Alexey1100 commented 3 years ago

Looking for a good practice when using decorated objects inside templates broadcasted with Turbo::Broadcastable.

Since the rendering happens in Turbo::Streams::ActionBroadcastJob, the objects are getting serialised (#817) and the decoration is lost.

class Clearance < ApplicationRecord
  belongs_to :petitioner, class_name: "Contact"
  belongs_to :examiner,   class_name: "User"

  after_create_commit :broadcast_later

  private

    # Sends <turbo-stream action="replace" target="clearance_5"><template><div id="clearance_5">Other partial</div></template></turbo-stream>
    # to the stream named "identity:2:clearances"
    def broadcast_later
      broadcast_replace_later_to examiner.identity, :clearances, target: self, partial: "clearances/other_partial", locals: { clearance: self }
    end
end
Alexey1100 commented 3 years ago

This is the quick solution I'm using currently, overriding the Turbo::Streams::ActionBroadcastJob job, as pointed by dhh in https://github.com/hotwired/turbo-rails/issues/190

class Turbo::Streams::ActionBroadcastJob < ApplicationJob
  def perform(stream, action:, target:, **rendering)
    rendering[:locals]&.transform_values! do |v|
      v.decorate
    rescue Draper::UninferrableDecoratorError, NoMethodError
      v
    end

    Turbo::StreamsChannel.broadcast_action_to stream, action: action, target: target, **rendering
  end
end