【问题标题】:Rails 5: ActionCable and db not being synchronizedRails 5:ActionCable 和 db 未同步
【发布时间】:2016-01-22 20:08:38
【问题描述】:

我能够成功设置 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.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 创建和广播帖子时,才能在数据库中找到它。如果我重新加载页面,我们刚刚创建的帖子就会起作用。不知道为什么在数据库中找不到新广播的帖子

【问题讨论】:

  • 您确定设置了params[:id] 吗?尝试使用params.fetch(:id) 确保密钥存在。可能是哈希只包含字符串键而不是符号。
  • params[:id] 100% 存在
  • 您从哪里获得在客户端传递的 ID? ID 是从页面的 id 或 data 属性中获取的吗?
  • 只是出于好奇-您是否尝试过使用find 而不是find_by_id?另外 - 你用的是什么数据库?
  • @Dani 使用 find 也不起作用,我使用的是 mySQL。当我运行 Post.order(id: :desc).limit(1) 时,它不会返回新创建的帖子,而是返回之前的帖子。

标签: ruby-on-rails ruby-on-rails-5 actioncable


【解决方案1】:

您是否在控制器中设置了两个广播?

ActionCable.server.broadcast 'Post(:id:)', { :data: }

否则,您可以同时流式传输

"Wall(#{profile.id})"

并在收到数据后添加逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 2017-09-19
    • 2017-04-02
    • 2016-11-22
    • 2017-03-13
    相关资源
    最近更新 更多