I am trying to create dynamic channels for users to chat in, but I am unable to pass the room_id
into the App.cable.subscriptions.create
call that is in the room.coffee
file. Any help in clarifying why I cannot use jQuery to get the value is extremely helpful.
This is what I receive back in the console:
RoomChannel is transmitting the subscription confirmation
RoomChannel is streaming from room__channel
RoomsController
class RoomsController < ApplicationController
before_action :authenticate_user!
def show
other_user = User.find(params[:id])
title = [other_user.id.to_s, current_user.id.to_s].sort!.join("-")
@room = Room.where(title: title).first
if @room.nil?
@room = Room.create! title: title
else
@messages = Message.where(room_id: @room[:id])
end
end
end
show.html.erb
<h1>Chat Room</h1>
<div id="messages">
<% if @messages.blank? %>
<div id="no_messages_yet">
<p>No messages yet...</p>
</div>
<% else %>
<%= render @messages %>
<% end %>
</div>
<form>
<label>Say something:</label><br>
<input type="text" data-behavior="room_speaker">
<input type="hidden" value="<%= @room[:id] %>" id="room_id">
<input type="hidden" value="<%= current_user[:id] %>" id="user_id">
</form>
views/messages/_message.html.erb
<div class="message">
<p><%= message.content %></p>
</div>
room.coffee
$(document).ready ->
room_id = $("#room_id").val()
console.log(room_id)
// => 1
// When I try and pass 'room_id' as the value for room_id:, I get an error stating the variable is not recognized.
App.room = App.cable.subscriptions.create {channel: "RoomChannel", room_id: $('#room_id').val()},
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
$('#messages').append data['message']
# Called when there's incoming data on the websocket for this channel
speak: (message, room_id, user_id) ->
@perform 'speak', message: message, room_id: room_id, user_id: user_id
$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
if event.keyCode is 13 # return = send
App.room.speak event.target.value, $('#room_id').val(), $('#user_id').val()
event.target.value = ""
event.preventDefault()
RoomChannel
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_#{params[:room_id]}_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def speak(data)
m = Message.new
m.user_id = data["user_id"]
m.room_id = data["room_id"]
m.content = data["message"]
m.save!
end
end
message.rb
class Message < ApplicationRecord
after_create_commit { MessageBroadcastJob.perform_later self }
end
jobs/message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
queue_as :default
def perform(message)
ActionCable.server.broadcast "room_#{message.room_id}_channel", message: render_message(message)
end
private
def render_message(message)
ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message })
end
end
Place the functionality inside the $(document).ready
call. Remember coffeescript is very touchy when it comes to indentation and whitespace.
$(document).ready ->
room_id = $('#room_id').val()
App.room = App.cable.subscriptions.create {channel: "RoomChannel", room_id: room_id},
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
$('#messages').append data['message']
# Called when there's incoming data on the websocket for this channel
speak: (message, room_id, user_id) ->
@perform 'speak', message: message, room_id: room_id, user_id: user_id
$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
if event.keyCode is 13 # return = send
App.room.speak event.target.value, $('#room_id').val(), $('#user_id').val()
event.target.value = ""
event.preventDefault()
Easiest way would be pass the value into HTML as data attribute. And read that back from CoffeeScript with jQuery.
You can add it to messages
div or the form. Something like this:
<div id="messages" data-room-id="<%= params[:id] %>">
And in JavaScript, read it with:
$('#messages').data('room-id')
In vanilla JavaScript:
document.getElementById('messages').dataset.roomId
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.