diff --git a/app/controllers/api/v1/chats_controller.rb b/app/controllers/api/v1/chats_controller.rb new file mode 100644 index 0000000..af1e06c --- /dev/null +++ b/app/controllers/api/v1/chats_controller.rb @@ -0,0 +1,20 @@ +class Api::V1::ChatsController < ApplicationController + def index + room = Room.find_by(key: params[:room_key]) + if room.blank? + render json: { error: t("404 error") }, status: 404 + return + end + + if params[:cursor].present? + cursor = Chat.find_by(id: params[:cursor]) + if cursor.blank? + render json: { error: t("404 error") }, status: 404 + return + end + @chats = room.past_chats(10, cursor) + else + @chats = room.past_chats(10) + end + end +end diff --git a/app/models/chat.rb b/app/models/chat.rb index 6492af2..81cfc2a 100644 --- a/app/models/chat.rb +++ b/app/models/chat.rb @@ -7,6 +7,10 @@ class Chat < ApplicationRecord end scope :latest_by, ->(num) do - order(created_at: :desc).limit(num) + order(id: :desc).limit(num) + end + + scope :before, ->(cursor) do + where("id < ?", cursor) end end diff --git a/app/models/room.rb b/app/models/room.rb index c239cdb..3003926 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -56,8 +56,12 @@ def last_played_video videos.ended.order_by_end.last end - def past_chats(num) - chats.latest_by(num).reverse + def past_chats(num, cursor = nil) + if cursor.blank? + chats.latest_by(num).reverse + else + chats.before(cursor).latest_by(num).reverse + end end def online_users diff --git a/app/views/api/v1/chats/index.json.jbuilder b/app/views/api/v1/chats/index.json.jbuilder new file mode 100644 index 0000000..6d86a54 --- /dev/null +++ b/app/views/api/v1/chats/index.json.jbuilder @@ -0,0 +1,3 @@ +json.chats @chats do |chat| + json.partial! "chats/chat", chat: chat +end diff --git a/config/routes.rb b/config/routes.rb index 8613735..c214e0c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,6 +16,7 @@ get :recommend end end + resources :chats, only: [:index] get "joined_rooms", to: "users#joined_rooms" get "youtube/search", to: "youtube#search" get "youtube/video", to: "youtube#video" diff --git a/spec/channels/room_channel_spec.rb b/spec/channels/room_channel_spec.rb index d8a957c..4aeaacd 100644 --- a/spec/channels/room_channel_spec.rb +++ b/spec/channels/room_channel_spec.rb @@ -195,8 +195,8 @@ before { chat.save! } it "expect to have broadcast with chat" do expect { subject }.to have_broadcasted_to(target).with { |data| - expect(data).to be_json_eql(%("#{chat.message}")).at_path("data/past_chats/0/message") - expect(data).to be_json_eql(user.id).at_path("data/past_chats/0/user/id") + expect(data).to be_json_eql(%("#{chat.message}")).at_path("data/past_chats/1/message") + expect(data).to be_json_eql(user.id).at_path("data/past_chats/1/user/id") } end end diff --git a/spec/models/room_spec.rb b/spec/models/room_spec.rb index 12b1cec..01ed0ef 100644 --- a/spec/models/room_spec.rb +++ b/spec/models/room_spec.rb @@ -141,6 +141,17 @@ } it { is_expected.to eq [chat2, chat3] } end + + context "with cursor" do + subject { room.past_chats 2, chat3.id } + + before { + chat1.save! + chat2.save! + chat3.save! + } + it { is_expected.to eq [chat1, chat2] } + end end describe "#online_users" do diff --git a/spec/requests/api/v1/chats_spec.rb b/spec/requests/api/v1/chats_spec.rb new file mode 100644 index 0000000..e031905 --- /dev/null +++ b/spec/requests/api/v1/chats_spec.rb @@ -0,0 +1,53 @@ +require "rails_helper" + +describe "chats" do + let(:room) { create(:room) } + + describe "GET /api/v1/chats" do + let(:params) { { room_key: room.key } } + let!(:chat) { create(:user_chat, room: room) } + + context "with valid params" do + it "returns a chat", :autodoc do + is_expected.to eq 200 + body = response.body + expect(body).to be_json_eql(chat.id).at_path("chats/0/id") + end + end + + context "without room_key" do + let(:params) { {} } + + it { is_expected.to eq 404 } + end + + context "with invalid room_key" do + let(:params) { { room_key: "invalid_key" } } + + it { is_expected.to eq 404 } + end + + context "with valid cursor" do + let(:before_chat) { create(:user_chat, room: room) } + let(:params) { { room_key: room.key, cursor: before_chat.id } } + + it "returns a chat", :autodoc do + is_expected.to eq 200 + body = response.body + expect(body).to be_json_eql(chat.id).at_path("chats/0/id") + end + + it "dose not contain before_chat" do + is_expected.to eq 200 + body = response.body + expect(body).not_to have_json_path("chats/1/id") + end + end + + context "with invalid cursor" do + let(:params) { { room_key: room.key, cursor: "invalid" } } + + it { is_expected.to eq 404 } + end + end +end