【发布时间】:2021-06-05 15:56:16
【问题描述】:
我有两个模型:post 和 comment,第二个嵌套在第一个中。我想为 cmets 创建一个动作电缆。这是我为帖子制作的方法:它工作得非常好——在控制台中显示帖子的标题和内容。路线:
resources :posts do
resources :comments
end
root "posts#index"
mount ActionCable.server => '/cable'
帖子控制器:
class PostsController < ApplicationController
before_action :find_post, only: [:show, :update, :edit, :destroy]
after_action :publish_post, only: [:create]
def publish_post
ActionCable.server.broadcast "posts_channel", {title: @post.title, content: @post.content}
end
private
def find_post
@post = Post.find(params[:id])
end
end
posts_channel.rb 的代码:
class PostsChannel < ApplicationCable::Channel
def subscribed
stream_from "posts_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
posts_channel.js 的代码:
import consumer from "./consumer"
consumer.subscriptions.create("PostsChannel", {
connected() {
console.log('i am post')
// Called when the subscription is ready for use on the server
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) {
console.log(data)
// Called when there's incoming data on the websocket for this channel
}
});
我的 cmets 代码非常相似,这里是 cmets 控制器:
class CommentsController < ApplicationController
before_action :find_comment, only: [:destroy]
after_action :publish_comment, only: [:create]
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(params[:comment].permit(:name, :comment, :user_id, :best, :file))
redirect_to post_path(@post)
end
def publish_comment
ActionCable.server.broadcast "comments_channel", {title: @comment.name, content: @comment.comment}
end
private
def find_comment
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
end
end
cmets_channel.rb 和 cmets_channel.rb 一样,只是流到 cmets_channel.js,这里是 js 频道:
import consumer from "./consumer"
consumer.subscriptions.create("CommentsChannel", {
connected() {
console.log('I am comment')
// Called when the subscription is ready for use on the server
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) {
console.log(data)
// Called when there's incoming data on the websocket for this channel
}
});
我的代码可能有什么问题?我敢肯定,我在 JS 代码上做错了,它只是看不到我在帖子上创建的嵌套表单。正如我所说 - 帖子和 cmets 频道非常相同,但有关创建帖子的数据正在广播到我的控制台,但我的 cmets 不是,即使我在控制器中定义了应该看到哪个帖子和哪个评论系统。
【问题讨论】:
-
我猜原因是在创建评论之后-> redirect_to 立即发布页面,因此加载发布页面意味着重新创建评论订阅,但在评论之前调用 after_action
publish_comment频道被创建,评论频道不会收到数据。 -
你是对的,当我创建评论时 - 帖子页面正在刷新。那么有什么办法可以使这项工作?还是我需要将 Ajax 添加到 cmets 以使页面不会刷新? (此外,def 'publish_post' 也有属性 'after_action' 但由于某种原因它正在工作)
-
我认为您的代码没问题,因为我猜您的目的是广播新评论,对吧?现在假设你和我打开这篇文章(这个问题),我去创建评论页面创建评论,如果成功我将返回帖子页面(重新加载)显然我会看到评论,现在在你身边,您停留在帖子页面并且评论频道已经创建,因此显然您也会收到广播数据。您需要打开 2 个选项卡(或浏览器)来检查。
-
我已经尝试过了。我有两个不同的浏览器并测试了帖子,它们工作得非常好 - ApplicationCable 向我的第二个浏览器广播了新帖子,但我不明白 - 为什么它对 cmets 不起作用,如果它可以正确广播所有内容 - 它至少会发送评论数据到控制台,但我什么也没得到。如果你愿意 - 我可以给你发送 github 项目。
-
是的,因为它是用代码编写的。此外,如果它对您有用 - 它是在我采取行动之前从控制台获取的:CommentsChannel 正在传输订阅确认 CommentsChannel 正在从 cmets:cmets_channel PostsChannel 正在传输订阅确认 PostsChannel 正在从 posts_channel 传输
标签: javascript ruby-on-rails ruby actioncable