diff --git a/app/channels/room_channel.rb b/app/channels/room_channel.rb index 2436af1..cb41ae9 100644 --- a/app/channels/room_channel.rb +++ b/app/channels/room_channel.rb @@ -1,43 +1,47 @@ class RoomChannel < ApplicationCable::Channel - attr_reader :log + attr_reader :subscriber def subscribed room = Room.find_by(key: params[:room_key]) return reject if room.blank? || room.banned?(current_user) - @log = UserRoomLog.create! user: current_user, - room: room, - ip_address: ip_address + @subscriber = UserRoomLog.create! user: current_user, + room: room, + ip_address: ip_address - stream_for @log.uuid + stream_for @subscriber.uuid stream_from "room_#{room.id}" end def unsubscribed # 既に強制退出されているときは退出処理を行わない - return if @log.blank? || @log.room.banned?(current_user) - @log.exit + return if @subscriber.blank? || @subscriber.room.banned?(@subscriber.user) + @subscriber.exit end def now_playing_video - RoomChannel.broadcast_to @log.uuid, - render_now_playing_video_json(@log.room) + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + RoomChannel.broadcast_to @subscriber.uuid, + render_now_playing_video_json(@subscriber.room) end def play_list - RoomChannel.broadcast_to @log.uuid, - render_play_list_json(@log.room) + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + RoomChannel.broadcast_to @subscriber.uuid, + render_play_list_json(@subscriber.room) end def past_chats - RoomChannel.broadcast_to @log.uuid, - render_past_chats_json(@log.room) + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + RoomChannel.broadcast_to @subscriber.uuid, + render_past_chats_json(@subscriber.room) end def add_video(data) - return if current_user.blank? + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + return if @subscriber.user.blank? - video = @log.room.add_video(data["youtube_video_id"], current_user) + video = @subscriber.room.add_video(data["youtube_video_id"], @subscriber.user) return video if video.blank? add_message = video.add_user.name + "さんが「" + video.title + "」を追加しました。" Chat.create! room: video.room, @@ -48,28 +52,31 @@ def add_video(data) end def exit_force(data) - return if current_user.blank? + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + return if @subscriber.user.blank? target = User.find(data["user_id"]) - logs = @log.room.user_room_logs.online.where(user: target) - logs.each do |log| - RoomChannel.broadcast_to log.uuid, + online_subscribers = @subscriber.room.user_room_logs.online + target_subscribers = online_subscribers.where(user: target) + target_subscribers.each do |target_subscriber| + RoomChannel.broadcast_to target_subscriber.uuid, render_error_json("force exit") - log.exit + target_subscriber.exit end BanReport.create! target: target, - reporter: current_user, - room: @log.room, + reporter: @subscriber.user, + room: @subscriber.room, expiration_at: Time.now.utc + 60 * 60 * 24 end def message(data) - return if current_user.blank? + @subscriber.touch # rubocop:disable Rails/SkipsModelValidations + return if @subscriber.user.blank? - Chat.create! room: @log.room, + Chat.create! room: @subscriber.room, chat_type: "user", message: data["message"], - user: current_user + user: @subscriber.user end private diff --git a/app/models/user_room_log.rb b/app/models/user_room_log.rb index 180b9f2..33ef66b 100644 --- a/app/models/user_room_log.rb +++ b/app/models/user_room_log.rb @@ -7,7 +7,7 @@ class UserRoomLog < ApplicationRecord after_create :send_enter_message after_update :send_exit_message, if: proc { |log| log.exit_at_before_last_save.blank? && log.exit_at.present? } - scope :online, -> { where exit_at: nil } + scope :online, -> { where(exit_at: nil).where(updated_at: 1.hour.ago..Time.current) } def exit update! exit_at: Time.now.utc diff --git a/spec/channels/room_channel_spec.rb b/spec/channels/room_channel_spec.rb index d8a957c..bdfbaba 100644 --- a/spec/channels/room_channel_spec.rb +++ b/spec/channels/room_channel_spec.rb @@ -4,8 +4,8 @@ let(:room) { create(:room) } let(:room_key) { room.key } let(:user) { create(:user) } - let(:log) { subscription.log } - let(:target) { RoomChannel.broadcasting_for([RoomChannel.channel_name, log.uuid]) } + let(:subscriber) { subscription.subscriber } + let(:target) { RoomChannel.broadcasting_for([RoomChannel.channel_name, subscriber.uuid]) } let(:stream_from) { "room_" + room.id.to_s } let(:current_user) { user } before { stub_connection current_user: current_user, ip_address: "0.0.0.0" } @@ -103,7 +103,7 @@ before { subscribe room_key: room.key } it { expect { subject }.to change(Chat, :count).by(1) } it { expect { subject }.to change { room.online_users.count }.by(-1) } - it { expect { subject }.to change { log.exit_at }.from(nil).to(Time) } + it { expect { subject }.to change { subscriber.exit_at }.from(nil).to(Time) } context "without login" do let(:current_user) { nil } @@ -113,7 +113,7 @@ to change(Chat, :count).by(0). and change { room.online_users.count }.by(0) } - it { expect { subject }.to change { log.exit_at }.from(nil).to(Time) } + it { expect { subject }.to change { subscriber.exit_at }.from(nil).to(Time) } end context "of duplicate subscription" do @@ -124,7 +124,7 @@ to change(Chat, :count).by(0). and change { room.online_users.count }.by(0) } - it { expect { subject }.to change { log.exit_at }.from(nil).to(Time) } + it { expect { subject }.to change { subscriber.exit_at }.from(nil).to(Time) } end end diff --git a/spec/models/user_room_log_spec.rb b/spec/models/user_room_log_spec.rb index 212b76d..2aed68e 100644 --- a/spec/models/user_room_log_spec.rb +++ b/spec/models/user_room_log_spec.rb @@ -5,4 +5,36 @@ log = build(:user_room_log) expect(log).to be_valid end + + describe "#online" do + subject { UserRoomLog.online } + + let(:updated_at) { Time.now.utc } + + before { create(:user_room_log, exit_at: exit_at, updated_at: updated_at) } + + context "when exit_at is nil" do + let(:exit_at) { nil } + + it "returns a log" do + expect(subject.size).to eq 1 + end + + context "and updated_at is out of date" do + let(:updated_at) { Time.now.utc - 60 * 60 - 10 } + + it "did not returns a log" do + expect(subject.size).to eq 0 + end + end + end + + context "when exit_at exist" do + let(:exit_at) { Time.now.utc - 10 } + + it "did not returns a log" do + expect(subject.size).to eq 0 + end + end + end end