我正在使用Rails 5和ActionCable创建一个聊天室。我按照video on GoRails进行了设置。
我现在想根据current_user
是否发送消息来设置消息样式。
这是我的 views / messages / _message.html.erb partial:
<div class="<%= message.user == current_user ? 'bubble' : 'bubble bubble-alt' %>">
<%= message.body %>
</div>
如果我只是刷新页面,样式就有效。问题是,当Sidekiq作业呈现此部分(触发MessagesController.render(message)
)时,它不知道current_user
是谁,因为它没有正确的上下文,所以聊天无法正常工作。
我的问题是,我如何允许用户在彼此之间发送消息并根据他们是否是发件人来设置样式?使用ActionCable + Sidekiq?
以下是其他相关文件:
message_relay_job.rb
class MessageRelayJob < ApplicationJob
queue_as :high
def perform(message)
ActionCable.server.broadcast("chatrooms:#{message.chatroom.id}",
{
message: MessagesController.render(message),
chatroom_id: message.chatroom.id
}
)
end
end
chatrooms_channel.rb
class ChatroomsChannel < ApplicationCable::Channel
def subscribed
current_user.chatrooms.each do |chatroom|
stream_from "chatrooms:#{chatroom.id}"
end
end
def unsubscribed
stop_all_streams
end
def send_message(data)
@chatroom = Chatroom.find(data['chatroom_id'])
message = @chatroom.messages.create(body: data['body'], user: current_user)
MessageRelayJob.perform_later(message)
end
end
chatrooms.coffee
if $("meta[name='current-user']").length > 0
App.chatrooms = App.cable.subscriptions.create "ChatroomsChannel",
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) ->
# Called when there's incoming data on the websocket for this channel
active_chatroom = $("[data-behavior='messages'][data-chatroom-id='#{data.chatroom_id}']")
if active_chatroom.length > 0
active_chatroom.append(data.message)
else
$("[data-behavior='chatroom-link'][data-chatroom-id='#{data.chatroom_id}']").css("font-weight", "bold")
send_message: (chatroom_id, body) ->
@perform "send_message", {chatroom_id: chatroom_id, body: body}
cable.js
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer("/cable");
}).call(this);
chatrooms.coffee
$ ->
$('#new_message').on 'keypress', (e) ->
if e && e.keyCode == 13
e.preventDefault()
$(this).submit()
$('#new_message').on 'submit', (e) ->
e.preventDefault()
chatroom_id = $("[data-behavior='messages']").data("chatroom-id")
body = $('#message_body')
App.chatrooms.send_message(chatroom_id, body.val())
# Clear out the message box
body.val("")
渠道/ application_cable / connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', "User #{current_user.email} - id: #{current_user.id}"
end
private
def find_verified_user
verified_user = User.find_by_id(cookies.signed['user.id'])
if verified_user && cookies.signed['user.expires_at'] > Time.zone.now
verified_user
else
reject_unauthorized_connection
end
end
end
end
渠道/ application_cable / channel.rb
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end
chatroom_users_controller.rb
class ChatroomUsersController < ApplicationController
before_action :authenticate_user!
before_action :set_chatroom
def create
@chatroom_user = @chatroom.chatroom_users.where(user_id: current_user.id).first_or_create
redirect_to @chatroom
end
private
def set_chatroom
@chatroom = Chatroom.find(params[:chatroom_id])
end
end
chatrooms_controller.rb
class ChatroomsController < ApplicationController
before_action :authenticate_user!
before_action :set_chatroom, only: %i[show edit update destroy]
def show
@messages = @chatroom.messages.includes(:user).order(created_at: :asc)
end
def create
@chatroom = Chatroom.new(chatroom_params)
respond_to do |format|
if @chatroom.save
format.html { redirect_to @chatroom, notice: 'Chatroom was successfully created.' }
format.json { render :show, status: :created, location: @chatroom }
else
format.html { render :new }
format.json { render json: @chatroom.errors, status: :unprocessable_entity }
end
end
end
def messages
@chatrooms = Chatroom.all
end
private
def set_chatroom
@chatroom = Chatroom.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:warning] = 'Unable to find the specified conversation.'
redirect_to messages_path
end
def chatroom_params
params.require(:chatroom).permit(:name)
end
end
messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_chatroom
def create
message = @chatroom.messages.new(message_params)
message.user = current_user
message.save
MessageRelayJob.perform_later(message)
end
private
def set_chatroom
@chatroom = Chatroom.find(params[:chatroom_id])
end
def message_params
params.require(:message).permit(:body)
end
end
视图/消息/ create.js.erb
$('#new_message')[0].reset()
模型/ chatroom_user.rb
class ChatroomUser < ApplicationRecord
# Associations
belongs_to :chatroom
belongs_to :user
end
模型/ chatroom.rb
class Chatroom < ApplicationRecord
# Associations
has_many :chatroom_users
has_many :users, through: :chatroom_users
has_many :messages
end
模型/ message.rb
class Message < ApplicationRecord
# Associations
belongs_to :chatroom
belongs_to :user
end
模型/ user.rb
class User < ApplicationRecord
has_many :chatroom_users
has_many :chatrooms, through: :chatroom_users
has_many :messages
end
非常感谢任何帮助。提前谢谢!
答案 0 :(得分:1)
如果我理解正确,你可以将params传递给你工作中的渲染方法:
ApplicationController.render(
partial: 'your partial',
locals: { current_user: current_user and your other locals }
)
另外,当你执行你的工作时,你应该传递你的current_user
作为参数MessageRelayJob.perform_later(message, current_user.id)
在你的工作中,你可以找到current_user。