Rails 5: ActionCable and db not being synchronized
Asked Answered
B

1

6

I was able to successfully setup ActionCable, listen to channels, authenticate requests, etc. However, I am running into a weird bug when trying to connect to a channel right after creation (hard to explain, see below)

I have a setup, a profile has a wall and the wall contains many posts. Each posts has its own channel, and the wall itself has its own channel. When a post is created on a wall, it is updated through 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
    }
});

I simplified it, but this works as intended. When new posts are created the wall channel gets triggered, client receives the post and all good.

The problem is connecting the new posts that were broadcasted. When I go to listen to the new post it fails to fetch the post from the db:

# 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
    }
});

Specifically the PostsChannel subscribed gets called with the proper id, but when it goes to grab the 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

it always returns null regardless of what happens. In other words it is failing to fetch the Post from the DB even though it 100% exists.

IF I have a few posts already on a wall they are able to successfully connect. ONLY when a post is created and broadcasted though ActionCable it is not able to be found in the DB. If I reload the page, the post that we just created works. Not sure why the newly broadcasted post isn't getting found in the db

Bes answered 22/1, 2016 at 20:8 Comment(7)
Are you sure that params[:id] is set? Try using params.fetch(:id) to ensure the key exists. It might be that the hash only consists of string keys and not symbols.Katlaps
params[:id] 100% existsBes
Where are you getting the ID that is being passed on the client-side? Is the ID being grabbed from a id or data attribute from the page?Isma
Just out of curiosity - have you tried using find instead of find_by_id? Also - what db are you using?Lucais
@Lucais Using find also does not work, I am using mySQL. When I run Post.order(id: :desc).limit(1) it doesn't return the newly created post, but the post before it.Bes
@Isma The ID is being passed through javascript, it never touches the dom.Bes
is the code hosted anywhere to take a look at?Isma
P
0

Did you set up both broadcasts in your controller?

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

Otherwise you can stream both from

"Wall(#{profile.id})"

and add logic after receiving the data.

Pebble answered 1/11, 2016 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.