Open garethrees opened 1 year ago
Here's a sketch
# Provide a convenience method on IncomingMessage
class IncomingMessage
def redelivery(editor:)
Redelivery.new(self, editor: editor)
end
end
# Extract redelivery to its own abstraction
class IncomingMessage::Redelivery
class AlreadyReelivered < StandardError ; end
def initialize(incoming_message, editor:)
@incoming_message = incoming_message
@editor = editor
@redelivered_to = []
@complete = false
end
attr_reader :redelivered_to
def redeliver(destination_requests)
raise AlreadyReelivered if complete?
ActiveRecord::Base.transaction do
# Redeliver the message to the destination requests
destination_requests.each do |destination_request|
destination_request.receive(
incoming_message.raw_email.mail,
incoming_message.raw_email.data,
override_stop_new_responses: true
)
incoming_message.info_request.log_event(
'redeliver_incoming',
editor: editor,
destination_request: destination_request.id,
deleted_incoming_message_id: incoming_message.id
)
@redelivered_to << destination_request
end
# Expire cached files
previous_request.expire
# Destroy the incoming message on the previous request
incoming_message.destroy!
# Mark as complete to prevent this redelivery being run again
@complete = true
end
end
def complete?
complete
end
protected
attr_reader :incoming_message, :editor, :complete
private
def previous_request
incoming_message.info_request
end
end
# Clean up the controller method
class AdminIncomingMessageController
def redeliver
message_ids = params[:url_title].split(',').map(&:strip)
destination_requests = requests_for_redelivery(message_ids)
redelivery = @incoming_message.redelivery(editor: current_user)
if redelivery.redeliver(destination_requests)
# TODO: Would be better to render a bulleted list destination requests
# that received the message
flash[:notice] =
"Message has been moved to request(s). Showing the last one:"
redirect_to admin_request_url(redelivery.redelivered_to.last)
else
flash[:error] = "Message could not be redelivered"
# render appropriate action with appropriate messaging
end
end
private
def requests_for_redelivery(message_ids)
destination_requests = []
# Look up each request and ensure each is valid
message_ids.each do |m|
destination_request =
if m.match(/^[0-9]+$/)
InfoRequest.find_by_id(m.to_i)
else
InfoRequest.find_by_url_title!(m)
end
if destination_request
destination_requests << destination_request
else
flash[:error] = "Failed to find destination request '#{m}'"
return redirect_to admin_request_url(previous_request)
end
end
# Handle the case that none are given
if destination_requests.empty?
flash[:error] =
"You must supply at least one request to redeliver the message to."
return redirect_to admin_request_url(previous_request)
end
destination_requests
end
end
We're starting to want to redeliver incoming messages from different places in the codebase. Ideally we'd have an abstraction for redelivering a message such that we don't have to redefine it everywhere.