• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mgmodell / devise-multi_email / #79

28 Mar 2026 03:16PM UTC coverage: 69.314% (-27.8%) from 97.112%
#79

push

mgmodell
trying to clean up some errors and update tests

192 of 277 relevant lines covered (69.31%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.81
/lib/devise/multi_email/models/validatable.rb
1
require 'devise/multi_email/parent_model_extensions'
1✔
2

3
module Devise
1✔
4
  module Models
1✔
5
    module EmailValidatable
1✔
6
      extend ActiveSupport::Concern
1✔
7

8
      included do
1✔
9
        validates_presence_of   :email, if: :email_required?
1✔
10
        validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :devise_will_save_change_to_email?
1✔
11
        validates_format_of     :email, with: email_regexp, allow_blank: true, if: :devise_will_save_change_to_email?
1✔
12
      end
13

14
      def email_required?
1✔
15
        true
×
16
      end
17

18
      module ClassMethods
1✔
19
        Devise::Models.config(self, :email_regexp)
1✔
20
      end
21
    end
22

23
    module MultiEmailValidatable
1✔
24
      extend ActiveSupport::Concern
1✔
25

26
      included do
1✔
27
        include Devise::MultiEmail::ParentModelExtensions
1✔
28

29
        assert_validations_api!(self)
1✔
30

31
        validates_presence_of     :email, if: :email_required?
1✔
32

33
        validates_presence_of     :password, if: :password_required?
1✔
34
        validates_confirmation_of :password, if: :password_required?
1✔
35
        validates_length_of       :password, within: password_length, allow_blank: true
1✔
36

37
        after_validation :propagate_email_errors
1✔
38

39
        multi_email_association.include_module(EmailValidatable)
1✔
40

41
        devise_modules << :validatable
1✔
42
      end
43

44
      def self.required_fields(_klass)
1✔
45
        []
×
46
      end
47

48
      protected
1✔
49

50
      # Same as Devise::Models::Validatable#password_required?
51
      def password_required?
1✔
52
        !persisted? || !password.nil? || !password_confirmation.nil?
×
53
      end
54

55
      # Same as Devise::Models::Validatable#email_required?
56
      def email_required?
1✔
57
        true
×
58
      end
59

60
      private
1✔
61

62
      def propagate_email_errors
1✔
63
        association_name = self.class.multi_email_association.name
×
64
        email_error_key = errors_attribute_names.detect do |key|
×
65
          [association_name.to_s, "#{association_name}.email"].include?(key.to_s)
×
66
        end
67
        return unless email_error_key.present?
×
68

69
        email_errors =
70
          if errors.respond_to?(:details)
×
71
            errors
×
72
              .details[email_error_key]
73
              .map { |e| e[:error] }
×
74
              .zip(errors.delete(email_error_key) || [])
75
          else
76
            errors.delete(email_error_key)
×
77
          end
78

79
        email_errors.each do |type, message|
×
80
          errors.add(:email, type, message: message)
×
81
        end
82
      end
83

84
      def errors_attribute_names
1✔
85
        errors.respond_to?(:attribute_names) ? errors.attribute_names : errors.keys
×
86
      end
87

88
      module ClassMethods
1✔
89
        # All validations used by this module.
90
        VALIDATIONS = %i[validates_presence_of validates_uniqueness_of validates_format_of
1✔
91
                         validates_confirmation_of validates_length_of].freeze
92

93
        def assert_validations_api!(base) # :nodoc:
1✔
94
          unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }
6✔
95

96
          return if unavailable_validations.empty?
1✔
97

98
          raise "Could not use :validatable module since #{base} does not respond " <<
×
99
                "to the following methods: #{unavailable_validations.to_sentence}."
100
        end
101

102
        Devise::Models.config(self, :password_length)
1✔
103
      end
104
    end
105
  end
106
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc