179ae45bf3
I went with placing htis logic at the command level since it plays well with the composite structure, where you don't know whether you are handling one command or many commands, and you want to aggregate all the errors. I didn't leverage the existing support with rails' model errors because that customizing those message is cumbersome (either i18n or using custom validation logic for everything).
75 lines
2.1 KiB
Ruby
75 lines
2.1 KiB
Ruby
class CommandsController < ApplicationController
|
|
def index
|
|
@commands = Current.user.commands.root.order(created_at: :desc).limit(20).reverse
|
|
end
|
|
|
|
def create
|
|
command = parse_command(params[:command])
|
|
|
|
if command.valid?
|
|
if confirmed?(command)
|
|
command.save!
|
|
result = command.execute
|
|
respond_with_execution_result(result)
|
|
else
|
|
respond_with_needs_confirmation(command)
|
|
end
|
|
else
|
|
respond_with_error(command)
|
|
end
|
|
end
|
|
|
|
private
|
|
def parse_command(string)
|
|
command_parser.parse(string)
|
|
end
|
|
|
|
def command_parser
|
|
@command_parser ||= Command::Parser.new(parsing_context)
|
|
end
|
|
|
|
def parsing_context
|
|
@parsing_context ||= Command::Parser::Context.new(Current.user, url: request.referrer)
|
|
end
|
|
|
|
def confirmed?(command)
|
|
!command.needs_confirmation? || params[:confirmed].present?
|
|
end
|
|
|
|
def respond_with_execution_result(result)
|
|
case result
|
|
when Array
|
|
respond_with_composite_response(result)
|
|
when Command::Result::Redirection
|
|
redirect_to result.url
|
|
when Command::Result::InsightResponse
|
|
respond_with_insight_response(result)
|
|
else
|
|
redirect_back_or_to root_path
|
|
end
|
|
end
|
|
|
|
def respond_with_needs_confirmation(command)
|
|
redirection_url = command.context.url unless command.context.url == parsing_context.url
|
|
render json: { confirmation: command.confirmation_prompt, redirect_to: redirection_url }, status: :conflict
|
|
end
|
|
|
|
def respond_with_composite_response(results)
|
|
json = results.map(&:as_json).grep(Hash).reduce({}, :merge)
|
|
if json.empty?
|
|
redirect_back_or_to root_path
|
|
else
|
|
render json: json, status: :accepted
|
|
end
|
|
end
|
|
|
|
def respond_with_insight_response(chat_response)
|
|
render json: { message: chat_response.content }, status: :accepted
|
|
end
|
|
|
|
def respond_with_error(command)
|
|
error_message = command.error_messages.map { |msg| "- #{msg}\n" }.join
|
|
render json: { error: error_message, context_url: command.context.url }, status: :unprocessable_entity
|
|
end
|
|
end
|