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).
50 lines
998 B
Ruby
50 lines
998 B
Ruby
# A composite of commands
|
|
class Command::Composite < Command
|
|
store_accessor :data, :title
|
|
|
|
has_many :commands, inverse_of: :parent, dependent: :destroy
|
|
|
|
def execute
|
|
ApplicationRecord.transaction do
|
|
commands.collect { it.execute }
|
|
end
|
|
end
|
|
|
|
def undo
|
|
ApplicationRecord.transaction do
|
|
undoable_commands.collect { it.undo }
|
|
end
|
|
end
|
|
|
|
def undoable?
|
|
undoable_commands.any?
|
|
end
|
|
|
|
def confirmation_prompt
|
|
confirmations = commands_excluding_redirections.collect(&:confirmation_prompt).collect { "- #{it}." }.join("\n")
|
|
|
|
<<~MD
|
|
You are about to:
|
|
|
|
#{confirmations}
|
|
MD
|
|
end
|
|
|
|
def needs_confirmation?
|
|
commands.any?(&:needs_confirmation?)
|
|
end
|
|
|
|
def error_messages
|
|
commands.flat_map(&:error_messages).uniq
|
|
end
|
|
|
|
private
|
|
def commands_excluding_redirections
|
|
commands.reject { it.is_a?(Command::VisitUrl) }
|
|
end
|
|
|
|
def undoable_commands
|
|
@undoable_commands ||= commands.filter(&:undoable?).reverse
|
|
end
|
|
end
|