My Rails app broadcasts a set of records via Action Cable,
ActionCable.server.broadcast 'model_channel', models: (ApplicationController.render 'models/index.json', assigns: { models: Model.all })
I'm calling ApplicationController.render
to ensure jbuilder
is invoked (I'm adding custom fields in my models/index.json.jbuilder
file).
All works fine EXCEPT that the broadcast
argument is converted to a string, thus I need to call JSON.parse(data['models'])
in order for the data to be used in the JavaScript handler.
Is there anything I can do on the Ruby side to avoid string-ifying my payload and then parsing it on the client side?
My Rails app broadcasts a set of records via Action Cable,
ActionCable.server.broadcast 'model_channel', models: (ApplicationController.render 'models/index.json', assigns: { models: Model.all })
I'm calling ApplicationController.render
to ensure jbuilder
is invoked (I'm adding custom fields in my models/index.json.jbuilder
file).
All works fine EXCEPT that the broadcast
argument is converted to a string, thus I need to call JSON.parse(data['models'])
in order for the data to be used in the JavaScript handler.
Is there anything I can do on the Ruby side to avoid string-ifying my payload and then parsing it on the client side?
Share Improve this question edited Aug 25, 2016 at 13:11 sambecker asked Aug 23, 2016 at 14:14 sambeckersambecker 1,1391 gold badge12 silver badges28 bronze badges 03 Answers
Reset to default 6You can use Jbuilder directly (i.e. without that parsing step) by passing in an external builder instance to the renderer, as in this code for example:
class ReservationChannel < ApplicationCable::Channel
def subscribed
reservation = Reservation.find(params[:reservation_id])
stream_for reservation
end
def self.reservation_update(reservation)
broadcast_to reservation, reservation_data_for_json(reservation)
end
private
def self.reservation_data_for_json(reservation)
Jbuilder.new do |json|
ApplicationController.render(
template: 'reservation/index.jbuilder',
locals: { reservation: reservation, json: json }
)
end.attributes!
end
end
I use the following helpers to return JSON data on client side
module ChannelHelper
def render_view(params)
ApplicationController.render(params)
end
def render_json(params)
JSON.parse render_view(params)
end
def broadcast channel, message
ActionCable.server.broadcast channel, message
end
end
and after that in channel
# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
class NotesChannel < ApplicationCable::Channel
include ChannelHelper
def subscribed
stream_from "notes_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def random
broadcast 'notes_channel', render_json(
template: 'notes/ws_random',
locals: { note: Note.random.first }
)
end
end
A mit form my pet-project which demonstrate how it works
https://github./DeployRB/Rails5App/mit/14485b2c3311e6bd25e6ce841f2f7ee3f83954ff
If you are using typical Rails scaffolding, you can do something like this (this example assumes @model is set to the model you want, as in a controller):
json = ApplicationController.render(partial: 'model/model.json',
locals {model: @model})
JSON.parse(json)