質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Action Cable

Action Cableは、WebSocketをRailsに組み込む機能。Rails4でオプションとして存在していたWebSocketをRails5で標準機能したものです。Railsアプリケーションと同様のスタイルで、Rubyを用いたリアルタイム機能を記述できます。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

2488閲覧

Rails ActionCable ページをリロードしないとチャット(DM)が更新されない

hapiblog2020

総合スコア1

Action Cable

Action Cableは、WebSocketをRailsに組み込む機能。Rails4でオプションとして存在していたWebSocketをRails5で標準機能したものです。Railsアプリケーションと同様のスタイルで、Rubyを用いたリアルタイム機能を記述できます。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/04/13 04:56

##はじめに

私は、現在、Rails5でポートフォリオ作成中の初学者です。

Action Cableを用いてDM機能(チャット機能)を実装しているのですが、
チャットを送った後、リロードしないと送ったメッセージが表示されません。

##実装の参考にした記事
Rails 5 + ActionCableで作る!シンプルなチャットアプリ(DHH氏のデモ動画より)

[Rails]ActionCableを使用してリアルタイムチャットの実装

リアルタイムチャットは誰でもつくれるAction CableでDM機能を作ろう

など

##メッセージ送信後のターミナル出力結果

出力結果はこちらです。
※見やすいように適宜改行しています。

Terminal

1DirectMessage Create (0.5ms) INSERT INTO "direct_messages" ("user_id", "room_id", "message", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["user_id", 4], ["room_id", 6], ["message", "そそそ"], ["created_at", "2021-04-13 04:18:35.981227"], ["updated_at", "2021-04-13 04:18:35.981227"]] 2 ↳ app/channels/room_channel.rb:13 3 (3.4ms) commit transaction 4 ↳ app/channels/room_channel.rb:13 5Could not execute command from ({"command"=>"message", "identifier"=>"{\"channel\":\"RoomChannel\",\"room\":6}", "data"=>"{\"direct_message\":\"そそそ\",\"action\":\"speak\"}"}) 6[RuntimeError - Circular dependency detected while autoloading constant ApplicationJob] 7: /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activesupport-5.2.5/lib/active_support/dependencies.rb:508:in `load_missing_constant' 8| /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activesupport-5.2.5/lib/active_support/dependencies.rb:195:in `const_missing' 9| /home/ec2-user/environment/enrich-ity/app/jobs/application_job.rb:1:in `<main>' | /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load' 10| /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'

調べたところ、Railsでは一度読み込んだファイルをキャッシュして2回目は読み込まないようにしているため、このようにエラーがでるみたいです。

[RuntimeError - Circular dependency detected while autoloading constant ApplicationJob]:

参考にした記事①

参考にした記事②

上記記事を参考に色々試行錯誤しましたが解決できませんでした。

##ソースコード

※リロードすればメッセージを表示することは可能なので、viewファイルの記述は間違っていないと思います。

#######db/schema.rb

create_table "direct_messages", force: :cascade do |t| t.integer "user_id", null: false t.integer "room_id", null: false t.string "message", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end

#######rooms_controller.rb

class Public::RoomsController < ApplicationController before_action :authenticate_user! def create @room = Room.create(:name => "DM") @entry1 = Entry.create(:room_id => @room.id, :user_id => current_user.id) @entry2 = Entry.create(params.require(:entry).permit(:user_id, :room_id).merge(:room_id => @room.id)) redirect_to room_path(@room.id) end def show @room = Room.find(params[:id]) if Entry.where(:user_id => current_user.id, :room_id => @room.id).present? @direct_messages = @room.direct_messages @entries = @room.entries else redirect_back(fallback_location: root_path) end end end

#######cable.js

// Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. // //= require action_cable //= require_self //= require_tree ./channels (function() { this.App || (this.App = {}); /* global ActionCable */ App.cable = ActionCable.createConsumer(); }).call(this);

#######room.coffee

document.addEventListener 'turbolinks:load', -> if App.room App.cable.subscriptions.remove App.room App.room = App.cable.subscriptions.create { channel: "RoomChannel", room: $('#direct_messages').data('room_id') }, connected: -> disconnected: -> received: (data) -> $('#direct_messages').append data['direct_message'] speak: (direct_message) -> @perform 'speak', direct_message: direct_message $(document).on 'keypress', '[data-behavior~=room_speaker]', (event) -> if event.keyCode is 13 App.room.speak event.target.value event.target.value = '' event.preventDefault()

#######connection.rb

module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end protected def find_verified_user #こっちの書き方だとメッセージをcreateできない # if verified_user = User.find_by(id: cookies.encrypted[:user_id]) # verified_user # else # reject_unauthorized_connection # end verified_user = User.find_by(id: env['warden'].user.id) return reject_unauthorized_connection unless verified_user verified_user end end end

#######room_cannel.rb

class RoomChannel < ApplicationCable::Channel def subscribed # stream_from "some_channel" stream_from "room_channel_#{params['room']}" end def unsubscribed # Any cleanup needed when channel is unsubscribed end def speak(data) DirectMessage.create! message: data['direct_message'], user_id: current_user.id, room_id: params['room'] end end

#######application_job.rb

class DirectMessageBroadcastJob < ApplicationJob queue_as :default def perform(direct_message) # マルチスレッド処理対策?書いても効果なし # Rails.application.eager_load! ActionCable.server.broadcast "room_channel_#{direct_message.room_id}", message: render_direct_message(direct_message) end private def render_direct_message(direct_message) # マルチスレッド処理対策?書いても効果なし # Rails.application.eager_load! ApplicationController.renderer.render(partial: 'direct_messages/direct_message', locals: { direct_message: direct_message }) end end

#######direct_message_broadcast_job.rb

class DirectMessageBroadcastJob < ApplicationJob queue_as :default def perform(direct_message) ActionCable.server.broadcast "room_channel_#{direct_message.room_id}", direct_message: render_direct_message(direct_message) end private def render_direct_message(direct_message) ApplicationController.renderer.render(partial: 'direct_messages/direct_message', locals: { direct_message: direct_message }) end end

#######direct_message.rb

class DirectMessage < ApplicationRecord belongs_to :user belongs_to :room has_many :notifications validates :message, presence: true after_create_commit { DirectMessageBroadcastJob.perform_later self } end

#######config/application.rb

require_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module EnrichIty class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag } config.i18n.default_locale = :ja config.time_zone = 'Tokyo' config.active_record.default_timezone = :local # マルチスレッド処理対策?書いても効果なし config.eager_load_paths += %W(#{config.root}/.rvm/gems/ruby-2.6.3/gems/activesupport-5.2.5/lib/active_support/dependencies.rb) # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. end end

2日間このエラーと戦っています。
初学者故に拙い知識での質問になりますが、
ご回答のほど、何卒よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

application_job.rbには何も追加で書く必要がなかったみたいです。

Baseからの継承が必要

class ApplicationJob < ActiveJob::Base end

また、管理者と会員側でviewファイルを分けていた為、renderも修正が必要でした。

direct_message_broadcast_job.rb

private def render_direct_message(direct_message) ApplicationController.renderer.render(partial: 'public/direct_messages/direct_message', locals: { direct_message: direct_message }) end #publicを追記

投稿2021/04/13 10:49

hapiblog2020

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問