最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Can you invoke Jbuilder to create a native Rails object instead of a rendered string? - Stack Overflow

matteradmin4PV0评论

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 0
Add a ment  | 

3 Answers 3

Reset to default 6

You 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)

Post a comment

comment list (0)

  1. No comments so far