1

I'm trying to create a chatroom channel, but when I post a message, the page reloads quickly (but the content doesn't update) and in the recieved function in chatroom_channel.js I have a console.log that doesn't trigger, but the console log in the connected function does.The new message only appears in the chatbox after I reload the page manually. Here's my code:

/* chatroom_channel.js */

import consumer from "./consumer"

consumer.subscriptions.create("ChatroomChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
    console.log('chatroom connected working')
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    console.log('recieved data')
  }
});

/* chatroom_channel.rb */

class ChatroomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chatroom_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

/* messages_controller.rb */

class MessagesController < ApplicationController

  # GET /messages or /messages.json
  def index
    @messages = Message.all
  end

  # POST /messages or /messages.json
  def create
    message = current_user.messages.build(message_params)
    if message.save
      ActionCable.server.broadcast("chatroom_channel", { body: message.body })
    end
  end

  private
    # Only allow a list of trusted parameters through.
    def message_params
      params.require(:message).permit(:body)
    end
end

/* cable.yml */

development:
  adapter: redis
  url: redis://localhost:6379/1

test:
  adapter: test

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: message_me_app_production

/* _chatbox.html.erb */

<div class="ui card fluid raised chatbox">
  <div class="content">
    <div class="ui feed">

    <%=render @messages%>

    </div>
  </div>
  <div class="extra content">
    <%= form_for(@message, html: {class: 'ui reply form'}, role: 'form', url: message_path) do |f|%>

        <div class="field">
          <div class="ui fluid icon input">
            <%=f.text_field :body%>
            <%=f.button '<i class="icon send"></i>'.html_safe, class: 'ui button primary'%>
          </div>
        </div>

    <%end%>
  </div>
</div>

/* index.html.erb */

<%if logged_in?%>
  <h2 class="ui center aligned icon header">
    <i class="circular coffee icon orange"></i>
    Say something
  </h2>
  <div class="ui two column grid">
    <div class="twelve wide column">
      <%=render 'chatbox'%>
    </div>
    <div class="four wide column">
      <div class="ui fluid raised card chatbox">
        <div class="content">
          <div class="ui inverted vertical menu">
            <a class="active item">
              Home
            </a>
            <a class="item">
              Messages
            </a>
            <a class="item">
              Friends
            </a>
          </div>
        </div>
      </div>
    </div>
  </div>
<%else%>
<h2 class="ui center aligned icon header">
    <i class="circular exclamation icon orange"></i>
    Log in to use the chatroom
  </h2>
<%end%>

/* connection.rb */

module ApplicationCable
  class Connection < ActionCable::Connection::Base
  end
end

/* routes.rb */

Rails.application.routes.draw do
  root 'chatroom#index'
  get 'login', to: 'sessions#new'
  post 'login', to: 'sessions#create'
  delete 'logout', to: 'sessions#destroy'
  post 'message', to: 'messages#create'
  resources :user

  mount ActionCable.server, at: '/cable'
end

EDIT: I added routes.rb file just in case

I checked that this is not a duplicate and I've read the following questions, but none of them worked for me: This This This

  • can you provide your connection.rb file please (I don't see anything wrong in the above also) – Maxence Nov 11 '21 at 21:58
  • Alright I'll update it right away – Ale Yanczuk Nov 11 '21 at 22:24
  • @Maxence Edited: I have a conection.rb file but it is empty – Ale Yanczuk Nov 11 '21 at 22:25
  • Ok you probably don't want to authenticate / authorize yet. I am not even sure an empty connection.rb file could be the culprit.. so it should be fine. Try to remove the Redis database from the url from `url: redis://localhost:6379/1` to `url: redis://localhost:6379`. Also do you have the gem `redis` in your gemfile ? – Maxence Nov 11 '21 at 22:42
  • @Maxence yes, redis is installed. I'll try to remove the database and check if it works, tanks! – Ale Yanczuk Nov 11 '21 at 22:50
  • @Maxence sadly,, it did not work. The behavior is still the same – Ale Yanczuk Nov 11 '21 at 22:54
  • What is strange is that you say the page "reloads quickly" when you send the message which should'nt happen as ActionCable and Websockets are full duplex. You should send your form async, though I see you are using a `form_for` and not the usual `form_with` which is async by default since it has been added in Rails 5. You can try to add `remote: true` to your `form_for` and see if it makes a difference... If you still struggle try another tutorial, sometimes some tiny bits can be overlooked by specific tutorials and better explained by others.. – Maxence Nov 11 '21 at 23:06
  • @Maxence thank you! Adding that to the form_for worked! I tested it by putting an alert() with the data and it worked well. If you dont mind me asking, what does "remote: true" do? Once again, thanks! – Ale Yanczuk Nov 11 '21 at 23:15
  • `remote: true` sends the form asynchronously (without leaving the current page). It uses Ajax (jquery). You can also send data async with pure JS like `fetch`. Basically you don't leave the current page and when you hit the controller asynchronously with a form data, the view expects a JSON response or a `create.js` file (Rails famous unobtrusive javascript) – Maxence Nov 11 '21 at 23:18
  • If you happen to replace your `form_for` by a `form_with` then your form will be async by default. You will need to add `local: true` to actually hit the controller and get an html.erb file in return. – Maxence Nov 11 '21 at 23:20
  • @Maxence alright! Thank you very much for the explanation – Ale Yanczuk Nov 11 '21 at 23:24

0 Answers0