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

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

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

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

Ruby on Rails 6

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

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Ruby on Rails

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2045閲覧

railsのActionCableを使ったチャットアプリでエラー ActionView::Template::Error (Devise could not find the `Warden::Pro

HTMLdoc

総合スコア67

Action Cable

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

Ruby on Rails 6

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

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Ruby on Rails

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/05/31 05:24

編集2020/06/02 01:22

rails 6.0.3
ruby 2.6.5
Mysql

railsでActionCableを使ったチャットアプリを作成しています。

しかしメッセージを送信したところで、

[ActiveJob] [MessageBroadcastJob] [b9536de0-7add-448c-8a4e-464fa65b1229] Error performing MessageBroadcastJob (Job ID: b9536de0-7add-448c-8a4e-464fa65b1229) from Async(default) in 10.09ms: ActionView::Template::Error (Devise could not find the `Warden::Proxy` instance on your request environment. Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack. If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.):

このようなエラーが出てしまいます。
ちなみに、メッセージ自体は保存することができます。
個人的にはjob関係がなにか悪いところがあるかと思いました。

コードを載せておきます。

_message.html.erb

erb

1<div class="message" id="message-<%= message.id %>"> 2 <div class="usernameAndTimeBox"> 3 <% unless message.user_id.nil? %> 4 <%= link_to message.username, user_path(message.user_id),class: "message_username" %> 5 <% else %> 6 <p class="message_username"><%= message.username %></p> 7 <% end %> 8 <p class="agomessage"><%= time_ago_in_words(message.created_at) + "前" %></p> 9 </div> 10 <% if user_signed_in? %> 11 <% if message.login == true %> 12 <%# if message.user_id == current_user.id %> 13 <button id="<%= message.id %>" class="delete_btn">削除</button> 14 <%# end %> 15 <% end %> 16 <% end %> 17 <%= raw Rinku.auto_link simple_format h(message.content), class: "message_content" %> 18 <% unless message.youtube_id.nil? %> 19 <% iframe = content_tag( 20 :iframe, 21 '', 22 width: 560, 23 height: 315, 24 src: "https://www.YouTube.com/embed/#{message.youtube_id}", 25 frameborder: 0, 26 allowfullscreen: true, 27 class: "youtube-container" 28 ) %> 29 <%= content_tag(:div, iframe, class: "youtube-container2") %> 30 <% end %> 31 <% if message.image? %> 32 <%= image_tag message.image.url %> 33 <% end %> 34<!-- <div class="editBox"> 35 <div class="formchat"> 36 <%#= form_with model: message, url: message_path(message) do |f| %> 37 <%#= f.rich_text_area :content %> 38 <%#= f.submit %> 39 <%# end %> 40 </div> 41 </div> --> 42</div>

message_broadcast_job.rb

rb

1class MessageBroadcastJob < ApplicationJob 2 queue_as :default 3 4 def perform(message) 5 ActionCable.server.broadcast "room_channel_#{message.room_id}", message: render_message(message) 6 end 7 8 private 9 def render_message(message) 10 ApplicationController.renderer.render partial: 'messages/message', locals: {message: message} 11 end 12end 13

room_channel.js

js

1import consumer from "./consumer" 2 $(function(){ 3 const chatChannel = consumer.subscriptions.create({channel: "RoomChannel", room: $('#messages').data('room_id') }, { 4 connected() { 5 // Called when the subscription is ready for use on the server 6 }, 7 8 disconnected() { 9 // Called when the subscription has been terminated by the server 10 }, 11 12 received(data) { 13 // 0.01秒たったら下に移動。 14 setTimeout(function(){ 15 var submitscroll = $('#bottomGO').offset().top; 16 $('html, body').scrollTop(submitscroll); 17 },10); 18 return $('#messages').append(data['message']); 19 20 // Called when there's incoming data on the websocket for this channel 21 }, 22 23 speak: function(message) { 24 return this.perform('speak', { 25 message: message 26 }); 27 } 28 }); 29 $(document).on('keypress submit click', '[data-behavior~=room_speaker]', function(event){ 30 31 console.log(event.target.value); 32 function chatgo(){ 33 chatChannel.speak(event.target.value); 34 event.target.value = ''; 35 return event.preventDefault(); 36 } 37 if(event.shiftKey){ 38 if(event.keyCode === 13){ 39 if(event.target.value != ''){ 40 chatgo(); 41 }else if(event.target.value == '' || event.target.length <= 1000){ 42 event.preventDefault(); 43 event.target.value = event.target.value; 44 } 45 } 46 } 47 $('#submit').click(function(){ 48 if(event.target.value != ''){ 49 chatgo(); 50 }else if(event.target.value == '' || event.target.length <= 1000){ 51 event.preventDefault(); 52 } 53 }); 54 }); 55 });

message.rb

rb

1class Message < ApplicationRecord 2 belongs_to :user, optional: true 3 belongs_to :room 4 # has_rich_text :content 5 validates :content, length: {maximum: 1000 } 6 after_create_commit { MessageBroadcastJob.perform_later self } 7 mount_uploader :image, ImageUploader 8 9 validate :image_size 10 11 private 12 13 def image_size 14 if image.size > 5.megabytes 15 errors.add(:image, "容量が大きすぎます。5MB未満のファイルにしてください。") 16 end 17 end 18end 19

次はメッセージを削除するところです。

room_delete_channel.js

js

1import consumer from "./consumer" 2$(function(){ 3 const deleteChannel = consumer.subscriptions.create({channel: "RoomDeleteChannel", room: $('#messages').data('room_id') }, { 4 connected() { 5 // Called when the subscription is ready for use on the server 6 7 }, 8 9 disconnected() { 10 // Called when the subscription has been terminated by the server 11 }, 12 13 received(data) { 14 $('#message-' + data['id']).remove(); 15 // Called when there's incoming data on the websocket for this channel 16 }, 17 18 delete: function(id) { 19 console.log("idGOGOGO") 20 return this.perform('delete', { 21 id: id 22 }); 23 } 24 }); 25 $(document).on('click', '.delete_btn', function(event){ 26 deleteChannel.delete(event.target.id) 27 // return event.preventDefault(); 28 }); 29});

room_delete_channel.rb

ruby

1class RoomDeleteChannel < ApplicationCable::Channel 2 def subscribed 3 stream_from "room_delete_channel" 4 end 5 6 def unsubscribed 7 # Any cleanup needed when channel is unsubscribed 8 end 9 10 def delete(data) 11 ActionCable.server.broadcast 'room_delete_channel', id: data['id'] 12 message = Message.find_by(id: data['id'], room_id: params['room'],user_id: current_user.id,login: true) 13 message.destroy 14 end 15end

current_userとipを扱うためのファイル
connection.rb

rb

1module ApplicationCable 2 class Connection < ActionCable::Connection::Base 3 identified_by :current_user 4 5   attr_accessor :ip_addr 6 def connect 7 self.current_user = find_verified_user 8    @ip_addr = request.ip 9 end 10 11 private 12 13 def find_verified_user 14 session_key = cookies.encrypted[Rails.application.config.session_options[:key]] 15 if session_key['warden.user.user.key'].present? 16 verified_id = session_key['warden.user.user.key'][0][0] 17 verified_user = User.find_by(id: verified_id) 18 return reject_unauthorized_connection unless verified_user 19 verified_user 20 else 21 return false 22 end 23 end 24 end 25end 26

追記

ActionCableで、メッセージを保存して、
ActionJobで、再度
ApplicationController.renderer.render

を使って、読み込むのですが、
読み込んだ先のファイルで
user_signed_in? と current_userなどの deiviseが用意しているヘルパーメソッドがエラーで使えなくなりました。

調べたらApplicationController.renderer.renderはenvに直接アクセスすることができないみたいです。

https://www.stefanwienert.de/blog/2016/04/05/using-rails-5-new-renderer-with-authentication-gems-like-clearance-or-devise/

このサイトを参考にして、やってみましたが、うまくいかず

ActionView::MissingTemplate (Missing template messages/message with {:locale=>[:ja], :formats=>[:html, :text, :js, :css, :ics, :csv, :vcf, :vtt, :png, :jpeg, :gif, :bmp, :tiff, :svg, :mpeg, :mp3, :ogg, :m4a, :webm, :mp4, :otf, :ttf, :woff, :woff2, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip, :gzip], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in: * "/home/vagrant/chatapp/app/views" * "/home/vagrant/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/devise-4.7.1/app/views" * "/home/vagrant/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actiontext-6.0.3/app/views" * "/home/vagrant/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/actionmailbox-6.0.3/app/views" ):

が出てしまいました。。。

修正してみたファイルを記述します。
message_broadcast_job.rb

rb

1class MessageBroadcastJob < ApplicationJob 2 queue_as :default 3 4 def perform(message) 5 ActionCable.server.broadcast "room_channel_#{message.room_id}", message: render_message(message) 6 end 7 private 8 9 def render_message(message) 10 11 # ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message }) 12 ApplicationController.render_with_signed_in_user(message.user_id, 'messages/message', locals: { message: message }) 13 end 14 15end 16

application.controller.rb

rb

1 ... 2 def self.render_with_signed_in_user(user, *args) 3 ActionController::Renderer::RACK_KEY_TRANSLATION['warden'] ||= 'warden' 4 proxy = Warden::Proxy.new({}, Warden::Manager.new({})).tap{|i| i.set_user(user, scope: :user) } 5 renderer = self.renderer.new('warden' => proxy) 6 puts "====================" + renderer.to_s 7 renderer.render(*args) 8 end 9end 10

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

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

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

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

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

guest

回答1

0

自己解決

application.controller.rbに

rb

1 def self.render_with_signed_in_user(user, *args) 2 ActionController::Renderer::RACK_KEY_TRANSLATION['warden'] ||= 'warden' 3 proxy = Warden::Proxy.new({}, Warden::Manager.new({})).tap{|i| i.set_user(user, scope: :user) } 4 renderer = self.renderer.new('warden' => proxy) 5 renderer.render(*args) 6 end

を追加して、
message_broadcast_job.rbに

rb

1class MessageBroadcastJob < ApplicationJob 2 queue_as :default 3 4 def perform(message) 5 ActionCable.server.broadcast "room_channel_#{message.room_id}", message: render_message(message) 6 end 7 private 8 9 def render_message(message) 10 # ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message }) 11 ApplicationController.render_with_signed_in_user(message.user, partial: 'messages/message', locals: { message: message }) 12 13 end 14 15end 16

とすることで解決しました。

jobだと、envにアクセスできないので、 application_controller.rbでアクセスできるようにします。

以下参考
https://www.stefanwienert.de/blog/2016/04/05/using-rails-5-new-renderer-with-authentication-gems-like-clearance-or-devise/

投稿2020/06/02 06:17

HTMLdoc

総合スコア67

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問