Rails 5: ActionCable и db не синхронизируются

Мне удалось успешно настроить 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 вызывается с правильным идентификатором, но когда он переходит к захвату сообщения:

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%.

ЕСЛИ у меня уже есть несколько сообщений на стене, они могут успешно соединиться. ТОЛЬКО когда сообщение создается и транслируется через ActionCable, его нельзя найти в БД. Если я перезагружу страницу, сообщение, которое мы только что создали, работает. Не уверен, почему недавно транслируемое сообщение не находится в базе данных.


person user3023421    schedule 22.01.2016    source источник
comment
Вы уверены, что установлено params[:id]? Попробуйте использовать params.fetch(:id), чтобы убедиться, что ключ существует. Возможно, хэш состоит только из строковых ключей, а не из символов.   -  person Linus Oleander    schedule 30.01.2016
comment
params[:id] 100% существует   -  person user3023421    schedule 31.01.2016
comment
Откуда вы получаете идентификатор, который передается на стороне клиента? Идентификатор захватывается из идентификатора или атрибута данных со страницы?   -  person cll    schedule 04.02.2016
comment
Просто из любопытства - вы пробовали использовать find вместо find_by_id? Кроме того, какую базу данных вы используете?   -  person Dani    schedule 04.02.2016
comment
@Dani Использование find также не работает, я использую mySQL. Когда я запускаю Post.order(id: :desc).limit(1), он возвращает не только что созданный пост, а пост перед ним.   -  person user3023421    schedule 05.02.2016
comment
@cll Идентификатор передается через javascript, он никогда не касается дома.   -  person user3023421    schedule 05.02.2016
comment
размещен ли код где-нибудь, чтобы взглянуть на него?   -  person cll    schedule 06.02.2016


Ответы (1)


Вы настроили обе трансляции в своем контроллере?

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

В противном случае вы можете транслировать оба из

"Wall(#{profile.id})"

и добавить логику после получения данных.

person Jeremy    schedule 01.11.2016