对于过滤器本身实际发生故障(例如黑名单不可用等)并通过true/false
返回值或如您还建议的那样抛出标签来指示有效/无效状态的情况,我会留下例外。
如果您不想在第一次失败时停止,但无论如何都要执行所有过滤器,您应该选择布尔返回类型并将它们连接在一起(success &= next_filter(msg)
)
如果我正确理解了您的情况,过滤器既可以修改消息,也可以检查其他来源的有效性(例如黑名单)。
所以我会这样做:
module MessageFilters
EmailValidator = ->(msg) do
throw :failure unless msg.txt =~ /@/
end
HTMLSanitizer = ->(msg) do
# this filter only modifies message, doesn't throw anything
# msg.text.remove_all_html!
end
end
class Message
attr_accessor :filters
def initialize
@filters = []
end
def execute_filters!
begin
catch(:failure) do
filters.each{|f| f.call self}
true # if all filters pass, this is returned, else nil
end
rescue => e
# Handle filter errors
end
end
end
message = Message.new
message.filters << MessageFilters::EmailValidator
message.filters << MessageFilters::HTMLSanitizer
success = message.execute_filters! # returns either true or nil