0

When i try to post an comment with ActionCable, everything works, however, i always have to refresh the page to see the comment itself get rendered. Any ideas whats wrong? Tried to restart the server, logout, login etc. But nothing really helped.

blogs.coffee

jQuery(document).on 'turbolinks:load', ->
  comments = $('#comments')
  if comments.length > 0
    App.global_chat = App.cable.subscriptions.create {
      channel: "BlogsChannel"
      blog_id: comments.data('blog-id')
    },
    connected: ->
    disconnected: ->
    recieved: (data) ->
      comments.append data['comment']
    send_comment: (comment, blog_id) ->
      @perform 'send_comment', comment: comment, blog_id: blog_id
  $('#new_comment').submit (e) ->
    $this = $(this)
    textarea = $this.find('#comment_content')
    if $.trim(textarea.val()).length > 1
      App.global_chat.send_comment textarea.val(),
      comments.data('blog-id')
      textarea.val('')
    e.preventDefault()
    return false

Blogs_channel.rb

class BlogsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "blogs_#{params['blog_id']}_channel"
  end

  def unsubscribed
  end

  def send_comment(data)
    current_user.comments.create!(content: data['comment'], blog_id: data['blog_id'])
  end
end

Comment.rb

class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :blog

  validates :content, presence: true, length: { minimum: 1, maximimum: 1000 }

  after_create_commit { CommentBroadcastJob.perform_later(self) }
end

CommentBroadcastJob.rb

class CommentBroadcastJob < ApplicationJob
  queue_as :default

  def perform(comment)
    ActionCable.server.broadcast "blogs_#{comment.blog.id}_channel", comment: render_comment(comment)
  end


  private

  def render_comment(comment)
    CommentsController.render partial: 'comments/comment', locals: { comment: comment }
  end
end

_comment.html.erb

<div class="comment-card">

  <div class="card">
    <div class="card-block">
      <div class="row">
        <div class="col-md-1">

        </div>

        <div class="col-md-11">
          <%= comment.content %>
        </div>
      </div>
    </div>
  </div>
</div>

The comment gets rendered inside the show.html.erb page with:

<%= render 'comments/comment_form' %>



<div id="comments" data-blog-id="<%= @blog.id %>">
  <%= render @blog.comments %>
</div>

Console log when submitting a new comment:

[ActionCable] [test1@test.com] [1] Finished "/cable/" [WebSocket] for 127.0.0.1 at 2017-12-21 09:42:47 +0100
[ActionCable] [test1@test.com] [1] BlogsChannel stopped streaming from blogs_3_channel
Started GET "/cable" for 127.0.0.1 at 2017-12-21 09:42:48 +0100
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2017-12-21 09:42:48 +0100
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
[ActionCable] [test1@test.com] [1] Registered connection (Z2lkOi8vdWRlbXktdHV0b3JpYWwtcmFpbHMvVXNlci8x)
[ActionCable] [test1@test.com] [1] BlogsChannel is transmitting the subscription confirmation
[ActionCable] [test1@test.com] [1] BlogsChannel is streaming from blogs_3_channel

No errors inside chrome console or whatsoever.

Any ideas? Inside route.rb i use mount ActionCable.server => '/cable' if this might help. It seems like it doesn't get activated / used, by no idea why.

Thanks in advance!

Edit:

At some point, i get the following error inside the terminal log:

[ActiveJob] [CommentBroadcastJob] [b32437ee-cf29-4323-97e9-841c87300518] Error performing CommentBroadcastJob (Job ID: b32437ee-cf29-4323-97e9-841c87300518) from Async(default) in 82.51ms: ActionView::Template::Error (undefined local variable or method `comment' for #<#<Class:0x00007f9b948bbed8>:0x00007f9b93a8fb98>
Did you mean?  ��comment):

Ran byebug under def perform, result:

[2, 11] in 
/app/jobs/comment_broadcast_job.rb
    2: class CommentBroadcastJob < ApplicationJob
    3:   queue_as :default
    4: 
    5:   def perform(comment)
    6:     byebug
=>  7:     ActionCable.server.broadcast "blogs_#{comment.blog.id}_channel", comment: render_comment(comment)
    8:   end

Well, why is comment undefined? Again, if i refresh the page, even with this error, i see the comment get rendered.

Prometheus
  • 799
  • 8
  • 28
  • where are you calling `CommentBroadcastJob`? From your code above, there is no trace where this is called. Furthermore (I'm no longer sure about this), but before / still even now, you should only pass in primitives like String or Integer as arguments to `perform` (because it's serialised by Sidekiq or DelayedJob, for example), so you'd probably instead want `def perform(comment_id) \n comment = Comment.find(comment_id)` – Jay-Ar Polidario Dec 21 '17 at 11:52
  • CommentBroadCast gets called by the Comment.rb with after_create_commit { CommentBroadcastJob.perform_later(self) } if im not wrong here (added the file in the OP). I'll check your suggestion out with the comment_id. – Prometheus Dec 21 '17 at 16:20
  • try passing the `id` instead of the `object` itself: `CommentBroadcastJob.perform_later(self.id)` but you'll need to also update your Job (see my previous comment) – Jay-Ar Polidario Dec 21 '17 at 16:26
  • Because the comment is created (as you have said that it shows after reloading the page), then surely enough everything worked fine even until your `after_create_commit`. Then, the 1st step to debug is if the background job is actually being processed. then can you insert `byebug` just above `ActionCable.server.broadcast "blogs_#{comment.blog.id}_channel", comment: render_comment(comment)`? If you haven't used byebug yet, this will then pause the server / sidekiq / delayed_job at that point so you can inspect stuff. If it didn't pause, then that means the job is not being ran, – Jay-Ar Polidario Dec 21 '17 at 16:33
  • Thanks for your suggestions. I've inserted byebug above the ActionCable.server.broadcast part. I've posted the results in the OP. – Prometheus Dec 21 '17 at 16:37
  • ahh looks good that the job is being processed properly. now lets try inspecting values. Can you enter `comment` on the byebug console? – Jay-Ar Polidario Dec 21 '17 at 18:22
  • if the comment record is there, lets try next if the value is actually received in the JS side: Above `comments.append data['comment']` can you insert `debugger`. If youre not familiar with debugger it basically just pauses your browser (but make sure you open your chrome debugging tool first for `debugger` to work). If your page paused (should look greyed out) after loading the page, then it means its currently paused at the line where debugger is called. If it didnt pause, then the problem lies somewhere in between transmission. – Jay-Ar Polidario Dec 21 '17 at 18:31
  • if it paused, then can you enter `data` in google chrome "console" tab. It should show the value of `data` that has been passed into your `receive(data)` function. Then afterwards just check the contents accordingly: `data.comment` should have the partial html value that youd expect – Jay-Ar Polidario Dec 21 '17 at 18:35
  • when i type in comment in byebug it pings the comment back i've tried to commit. Currently working on debugger, can't really install it, always get an error when i try to run bundle install / gem install. I'll see whats going on. Thanks so far for your support! – Prometheus Dec 21 '17 at 20:03
  • `debugger` is not a gem. You just insert that line as is. You don't need to install anything. See [here for details](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger) No problem :) – Jay-Ar Polidario Dec 21 '17 at 20:04
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161772/discussion-between-prometheus-and-jay-ar-polidario). – Prometheus Dec 21 '17 at 22:07
  • @Prometheus after debugging what was value returning in 'comment'? – ashvin Dec 22 '17 at 12:24
  • do you mean byebug? With byebug, when i ran 'comment' i got the value back with the content, the user id and the blog id that was submitted, which is exactly how it should be. If you mean debugger for coffee script, it didn't gave any errors back. I found the solution, even though i didn't found any typos on my own (see answer at the bottom). – Prometheus Dec 22 '17 at 16:01

1 Answers1

0

So i've copied the BroadCastJob.rb file from the original file (its from a course), and its finally working. I can't find any typo in my file vs. the instructors file. If anyone can find it, let me know.

My CommentBroadcastJob.rb file:

class CommentBroadcastJob < ApplicationJob
  queue_as :default

  def perform(comment)
    ActionCable.server.broadcast "blogs_#{comment.blog.id}_channel", comment: render_comment(comment)
  end


  private

  def render_comment(comment)
    CommentsController.render partial: 'comments/comment', locals: { comment: comment }
  end
end

the instructors one:

class CommentBroadcastJob < ApplicationJob
  queue_as :default

  def perform(comment)
    ActionCable.server.broadcast "blogs_#{comment.blog.id}_channel", comment: render_comment(comment)
  end

  private

  def render_comment(comment)
    CommentsController.render partial: 'comments/comment', locals: { comment: comment }
  end
end

which is working. Whenever i delete this one and use my one, i get the same error as before. When i use the instructor ones, it finally renders the message after sending it. No idea where the difference should be.

Prometheus
  • 799
  • 8
  • 28
  • Seeing as this question is over 2 years old, I am guessing that it is no longer an issue; but, I put your code into a test file and committed it to GitHub, then replaced the code in the file with the instructor's code and checked for differences. The only difference between the two codes you posted here is an extra line before the `private` declaration. That should not have an affect on how everything is run. So, I am unsure why simply replacing the code made it work. Are you sure there was no other code you changed? Are you using a code version tracker of some kind that you could help? – Christopher Warrington Dec 29 '19 at 14:37