rails 实时删除元素

rails remove element in real time

得到一个 link 从 current_users 屏幕上删除一条消息:

= link_to '[x]', msg, method: :delete, remote: true, class: "del-link"

它触发了这个 coffeescript-funktion:

delete_message = () ->
$('.del-link').on 'ajax:success', (event) ->
  event.preventDefault()
  $(this).closest('.message').remove()
  return

和这个rails-方法:

def destroy
  @msg = Msg.find(params[:id])
  @msg.destroy

  respond_to do |format|
    format.html { redirect_to chat_path }
    format.json { head :no_content }
    format.js   { render :layout => false }
  end
end

但是如何做到这一点,即在每个用户屏幕上删除该消息,例如使用 ActionCable?

聊天的 coffeescript:

App.proom = App.cable.subscriptions.create "ProomChannel",
  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) ->
    unless data.msg.blank?
        $('#messages-table').append data.msg
        scroll_bottom()


 $(document).on "turbolinks:load", ->
   submit_msg()
   scroll_bottom()
   delete_message()

channel.rb

class ProomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "proom_channel"
  end

  def unsubscribed
  end
end

方法

所以我将其添加到控制器的销毁操作中

if msg.destroy
  ActionCable.server.broadcast 'proom_channel', msg: @msg
end

我还为每个包含消息记录 ID 的消息-div-元素添加了一个 ID,以便使用以下行 DOM 查找并删除它

$("msg_#{msg.id}").remove()

但是现在不知道放在哪里

我现在不能给你完整的答案,但如果你找不到解决方案,我会稍后更新我的答案:

就像您使用动作电缆创建消息一样,在将消息保存在数据库中后,您会触发一个 ActionCable.server.broadcast 'messages',它将执行一些包含在用户浏览器资产管道文件中的 JS app/assets/javascripts/channels/messages.js ]

这是我的消息控制器,一旦我保存消息,我就会启动 Server.broadcast 进程。它将触发我的 messages_channel.rb 中的进程,该进程将更新订阅该频道的所有客户端。

  def create
    message = Message.new(message_params)
    message.user = current_user 
    chatroom = message.chatroom
    if message.save
        ActionCable.server.broadcast 'messages',
        message: message.content,
        user: message.user.name,
        chatroom_id: message.chatroom_id,
        lastuser: chatroom.messages.last(2)[0].user.name
      head :ok
    end
  end

图文来自以下文章Sophie DeBenedetto

We add our new subscription to our consumer with App.cable.subscriptions.create. We give this function an argument of the name of the channel to which we want to subscribe, MessagesChannel.

When this subscriptions.create function is invoked, it will invoke the MessagesChannel#subscribed method, which is in fact a callback method.

MessagesChannel#subscribed streams from our messages broadcast, sending along any new messages as JSON to the client-side subscription function.

Then, the received function is invoked, with an argument of this new message JSON. The received function in turn calls a helper function that we have defined, renderMessage, which simply appends new messages to the DOM, using the $("#messages") jQuery selector, which can be found on the chatroom show page.

频道将调用 messages.js 函数 received,这会将 div 附加到 DOM,您需要在 messages.js.

App.messages = App.cable.subscriptions.create('MessagesChannel', {      
  received: function(data) {
      // code executed - the parameters will be in data.chatroom_id and 
      // data.user, data.message etc...
  }
});

所以您需要从您的操作 messages#destroy 中调用频道,在 messages.js 中有一个特定的函数来从 DOM 中删除 div。 我不知道你是否需要创建一个特定的服务器端通道,或者你可以只编辑你现在的 messages_channel.rb 以包含一个特定的功能。你需要阅读指南并弄清楚这一点。我可以试试这在未来,但现在我不能

或者一个简单的替代方案,只需在 messages.js 中写一些 js 来解决这个问题,并在需要时删除 div.. 例如 messages#destroy 动作可以传递一个参数并且如果存在该参数,您将删除该消息,而不是添加它

https://github.com/rails/rails/tree/master/actioncable#channel-example-1-user-appearances