module ErrorsHelper # Displays an alert containing a list of error messages for a given model attribute def errors_for(model, attribute) ErrorsList.new(self, model, attribute).to_html end # Displays an alert containing a list of all the error messages for a given model def errors_summary_for(model) ErrorsSummary.new(self, model).to_html end private class ErrorsList def initialize(view, model, attribute) @view = view @model = model @attribute = attribute end def to_html return if errors.empty? error_list_items = errors.map { |error| content_tag(:li, error) } content_tag(:div, class: "alert alert-danger text-left") do concat content_tag(:p, message) concat content_tag(:ul, safe_join(error_list_items)) end end private attr_reader :view, :model, :attribute delegate :concat, :content_tag, :safe_join, to: :view def errors @errors ||= errors = model.errors[attribute] end def message "#{attribute.to_s.humanize} is not valid." end end class ErrorsSummary def initialize(view, model) @view = view @model = model end def to_html return if errors.empty? content_tag(:div, class: "alert alert-danger text-left") do concat content_tag(:p, translate("errors_helper.failure_message", model_name: name)) concat content_tag(:ul, safe_join(error_list_items)) end end private attr_reader :view, :model delegate :concat, :content_tag, :safe_join, :translate, to: :view def errors @errors ||= model.errors.full_messages end def error_list_items errors.map { |error| content_tag(:li, error) } end def name model.model_name.human.downcase end end end