Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion app/controllers/messages/by_bots_controller.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,54 @@
class Messages::ByBotsController < MessagesController
allow_bot_access only: :create
allow_bot_access only: %i[ index create ]

def index
set_room
@messages = find_paged_messages
render json: messages_as_json(@messages)
end

def create
super
head :created, location: message_url(@message)
end

private
def messages_as_json(messages)
{
room: {
id: @room.id,
name: @room.name
},
messages: messages.map { |m| message_as_json(m) },
pagination: pagination_info(messages)
}
end

def message_as_json(message)
{
id: message.id,
body: {
plain: message.plain_text_body,
html: message.body&.body&.to_s
},
created_at: message.created_at.iso8601,
creator: {
id: message.creator.id,
name: message.creator.name,
is_bot: message.creator.role == "bot"
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the enum predicate method bot? instead of comparing to the string "bot". This is consistent with how the codebase checks enum values elsewhere (e.g., administrator? in User::Role) and is the idiomatic Rails pattern for enum checks.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e8c1349 - now using message.creator.bot? which is the idiomatic Rails enum predicate pattern.

}
}
end

def pagination_info(messages)
return {} if messages.empty?
{
oldest_id: messages.last.id,
newest_id: messages.first.id,
has_more: messages.size == Message::PAGE_SIZE
}
end

def message_params
if params[:attachment]
params.permit(:attachment)
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
resources :rooms do
resources :messages

# Bot API endpoints - authenticated via bot_key in URL
get ":bot_key/messages", to: "messages/by_bots#index", as: :bot_messages_index
post ":bot_key/messages", to: "messages/by_bots#create", as: :bot_messages

scope module: "rooms" do
Expand Down
47 changes: 45 additions & 2 deletions test/controllers/messages/by_bots_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,51 @@ class Messages::ByBotsControlleTest < ActionDispatch::IntegrationTest
assert_response :redirect
end

test "denied index" do
get room_messages_url(@room, bot_key: users(:bender).bot_key, format: :json)
test "index returns messages as JSON" do
get room_bot_messages_index_url(@room, users(:bender).bot_key)
assert_response :success

json = JSON.parse(response.body)
assert json["room"]["id"].present?
assert json["room"]["name"].present?
assert json["messages"].is_a?(Array)
assert json["pagination"].present?
end

test "index includes message details" do
# Create a message in the room first
post room_bot_messages_url(@room, users(:bender).bot_key), params: +"Test message for index"

get room_bot_messages_index_url(@room, users(:bender).bot_key)
assert_response :success

json = JSON.parse(response.body)
message = json["messages"].find { |m| m["body"]["plain"] == "Test message for index" }
assert message.present?, "Expected to find the test message"
assert message["id"].present?
assert message["created_at"].present?
assert message["creator"]["id"].present?
assert message["creator"]["name"].present?
end

test "index supports pagination with before parameter" do
get room_bot_messages_index_url(@room, users(:bender).bot_key, before: Message.last.id)
assert_response :success
end

test "index supports pagination with after parameter" do
get room_bot_messages_index_url(@room, users(:bender).bot_key, after: Message.first.id)
assert_response :success
end
Comment on lines +88 to +93
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test uses Message.first.id which is 1, but message 1 belongs to the 'designers' room, not the 'watercooler' room (@room). When the controller tries to find this message in the watercooler room, it will raise a RecordNotFound error. Use a message ID that actually belongs to the watercooler room, such as creating a message in setup or using a message ID from the watercooler fixtures.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit c82a8d3 - now using messages(:fourth) and messages(:thirteenth) which are fixtures belonging to the watercooler room where the bender bot is a member.


test "index requires valid bot key" do
get room_bot_messages_index_url(@room, "invalid-bot-key")
assert_response :redirect # Redirects to login
end

test "regular messages index still denied for bots" do
# The standard messages endpoint (not the bot-specific one) should still be forbidden
get room_messages_url(@room, bot_key: users(:bender).bot_key)
assert_response :forbidden
end
end
Loading