首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 5:使用ActionCable和Sidekiq为用户聊天设置样式

Rails 5:使用ActionCable和Sidekiq为用户聊天设置样式
EN

Stack Overflow用户
提问于 2018-04-13 11:13:19
回答 1查看 727关注 0票数 1

我正在使用Rails 5和ActionCable创建一个聊天室。我跟踪GoRails上的视频来设置它。

现在,我想根据current_user是否发送消息来设置消息的样式。

这是我的views/messages/_message.html.erb部分:

代码语言:javascript
复制
<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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
(function() {
  this.App || (this.App = {});
  App.cable = ActionCable.createConsumer("/cable");
}).call(this);

chatrooms.coffee

代码语言:javascript
复制
$ ->
  $('#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("")

channels/application_cable/connection.rb

代码语言:javascript
复制
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

channels/application_cable/channel.rb

代码语言:javascript
复制
module ApplicationCable
  class Channel < ActionCable::Channel::Base
  end
end

chatroom_users_controller.rb

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

views/messages/create.js.erb

代码语言:javascript
复制
$('#new_message')[0].reset()

models/chatroom_user.rb

代码语言:javascript
复制
class ChatroomUser < ApplicationRecord
  # Associations
  belongs_to :chatroom
  belongs_to :user
end

models/chatroom.rb

代码语言:javascript
复制
class Chatroom < ApplicationRecord
  # Associations
  has_many :chatroom_users
  has_many :users, through: :chatroom_users
  has_many :messages
end

models/message.rb

代码语言:javascript
复制
class Message < ApplicationRecord
  # Associations
  belongs_to :chatroom
  belongs_to :user
end

models/user.rb

代码语言:javascript
复制
class User < ApplicationRecord
  has_many :chatroom_users
  has_many :chatrooms, through: :chatroom_users
  has_many :messages
end

任何帮助都是非常感谢的。提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2018-04-19 10:06:39

如果我正确理解,您可以在工作中将params传递到您的呈现方法中:

代码语言:javascript
复制
ApplicationController.render(
    partial: 'your partial',
    locals: { current_user: current_user and your other locals }
)

此外,当你执行你的工作时,你应该把你的current_user作为参数传递给你。

代码语言:javascript
复制
MessageRelayJob.perform_later(message, current_user.id)

在你的工作中,你可以找到current_user。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49815689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档