我成功地设置了ActionCable,监听频道,验证请求等。但是,当我尝试在创建后立即连接到频道时,遇到了一个奇怪的错误(很难解释,请参见下文)。
我的设置如下:一个个人资料有一个墙壁,这个墙壁包含许多帖子。每个帖子都有自己的频道,而墙壁本身也有自己的频道。当在墙上创建帖子时,它通过ActionCable进行更新:
# Wall's Cable Channel
class WallsChannel < ApplicationCable::Channel
def subscribed
profile = Profile.find_by_id params[:id]
if ability.can? :subscribe, profile
stream_from "Wall(#{profile.id})"
else
reject
end
end
end
# Broadcasting to the wall
ActionCable.server.broadcast 'Wall(:id:)', { :data: }
# Client Side
GlobalCable.cable.subscriptions.create({channel: 'WallsChannel', id :id: }, {
received: function(data) {
// do stuff with a new post on a wall
}
});
我简化了它,但它可以按预期工作。当创建新帖子时,会触发墙面频道,客户端接收帖子并一切正常。
问题是连接广播的新帖子。当我去听取新帖子时,无法从数据库获取帖子。
# Posts Cable Channel
class PostsChannel < ApplicationCable::Channel
def subscribed
post = Post.find_by_id params[:id]
if ability.can? :subscribe, post
stream_from "Post({#{post.id}})"
else
reject
end
end
end
# Client side
GlobalCable.cable.subscriptions.create({ channel: 'PostsChannel', id: id }, {
received: function(data) {
// do stuff
}
});
具体而言,订阅了PostsChannel的方法将以适当的id被调用,但是当它去获取post时:
post = Post.find_by_id params[:id]
# SQL that is generated
# SELECT `posts`.* FROM `posts` WHERE `posts`.`id` = :id: LIMIT 1
# ^ Always returns null even though we just created the post
无论发生什么情况,它始终返回null。换句话说,即使它100%存在,它也未能从数据库中获取Post。
如果墙上已经有几篇文章,它们可以成功连接。仅当通过ActionCable创建并广播文章时,它才无法在DB中找到。如果重新加载页面,则刚刚创建的文章有效。不确定为什么新广播的文章不能在db中找到。
params[:id]
已经设置了吗?尝试使用params.fetch(:id)
来确保该键存在。可能哈希表只包含字符串键而不是符号键。 - Linus Oleanderfind
而不是find_by_id
吗?另外 - 你正在使用哪个数据库? - Dani