Class: Message

Inherits:
Common::Base show all
Includes:
ActiveModel::Validations, RedisCaching
Defined in:
app/models/message.rb

Overview

Models a secure message

Direct Known Subclasses

MessageDraft, MessageThreadDetails

Constant Summary collapse

MAX_TOTAL_FILE_SIZE_MB =
10.0
MAX_SINGLE_FILE_SIZE_MB =
6.0

Instance Attribute Summary collapse

Attributes inherited from Common::Base

#errors_hash, #metadata

Instance Method Summary collapse

Methods inherited from Common::Base

#changed, #changed?, #changes, default_sort, filterable_attributes, max_per_page, per_page, sortable_attributes

Constructor Details

#initialize(attributes = {}) ⇒ Message

Returns a new instance of Message.



85
86
87
88
89
# File 'app/models/message.rb', line 85

def initialize(attributes = {})
  super(attributes)
  self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
  self.body = body ? Nokogiri::HTML.parse(body) : nil
end

Instance Attribute Details

#attachmentBoolean Also known as: attachment?

Returns:

  • (Boolean)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#attachmentsArray[Attachment]

Returns an array of Attachments.

Returns:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#bodyString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#categoryString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#idInteger

Returns:

  • (Integer)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#proxy_sender_nameString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#read_receiptString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#recipient_idInteger

Returns:

  • (Integer)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#recipient_nameString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#sender_idInteger

Returns:

  • (Integer)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#sender_nameString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#sent_dateCommon::UTCTime

Returns:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#subjectString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

#triage_group_nameString

Returns:

  • (String)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/message.rb', line 37

class Message < Common::Base
  per_page 10
  max_per_page 100

  MAX_TOTAL_FILE_SIZE_MB = 10.0
  MAX_SINGLE_FILE_SIZE_MB = 6.0

  include ActiveModel::Validations
  include RedisCaching

  redis_config REDIS_CONFIG[:secure_messaging_store]

  # Only validate presence of category, recipient_id if new message or new draft message
  validates :category, :recipient_id, presence: true, unless: proc { reply? }

  # Always require body to be present: new message, drafts, and replies
  validates :body, presence: true
  validates :uploads, length: { maximum: 4, message: 'has too many files (maximum is 4 files)' }

  # Only validate upload sizes if uploads are present.
  validate :each_upload_size_validation, if: proc { uploads.present? }
  validate :total_upload_size_validation, if: proc { uploads.present? }

  attribute :id, Integer
  attribute :category, String
  attribute :subject, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :body, String
  attribute :attachment, Boolean
  attribute :sent_date, Common::UTCTime, filterable: %w[eq lteq gteq], sortable: { order: 'DESC', default: true }
  attribute :sender_id, Integer
  attribute :sender_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :recipient_id, Integer
  attribute :recipient_name, String, filterable: %w[eq not_eq match], sortable: { order: 'ASC' }
  attribute :read_receipt, String
  attribute :triage_group_name, String
  attribute :proxy_sender_name, String
  attribute :attachments, Array[Attachment]
  attribute :has_attachments, Boolean
  attribute :attachment1_id, Integer
  attribute :attachment2_id, Integer
  attribute :attachment3_id, Integer
  attribute :attachment4_id, Integer

  # This is only used for validating uploaded files, never rendered
  attribute :uploads, Array[ActionDispatch::Http::UploadedFile]

  alias attachment? attachment

  def initialize(attributes = {})
    super(attributes)
    self.subject = subject ? Nokogiri::HTML.parse(subject) : nil
    self.body = body ? Nokogiri::HTML.parse(body) : nil
  end

  ##
  # @note Default sort should be sent date in descending order
  #
  def <=>(other)
    -(sent_date <=> other.sent_date)
  end

  ##
  # @note This returns self so that it can be chained: Message.new(params).as_reply
  #
  def as_reply
    @reply = true
    self
  end

  ##
  # @return [Boolean] is there a reply?
  #
  def reply?
    @reply || false
  end

  private

  def total_upload_size
    return 0 if uploads.blank?

    uploads.sum(&:size)
  end

  def total_upload_size_validation
    return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

    errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
  end

  def each_upload_size_validation
    uploads.each do |upload|
      next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

      errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
    end
  end
end

Instance Method Details

#<=>(other) ⇒ Object

Note:

Default sort should be sent date in descending order



94
95
96
# File 'app/models/message.rb', line 94

def <=>(other)
  -(sent_date <=> other.sent_date)
end

#as_replyObject

Note:

This returns self so that it can be chained: Message.new(params).as_reply



101
102
103
104
# File 'app/models/message.rb', line 101

def as_reply
  @reply = true
  self
end

#each_upload_size_validationObject (private)



127
128
129
130
131
132
133
# File 'app/models/message.rb', line 127

def each_upload_size_validation
  uploads.each do |upload|
    next if upload.size <= MAX_SINGLE_FILE_SIZE_MB.megabytes

    errors.add(:base, "The #{upload.original_filename} exceeds file size limit of #{MAX_SINGLE_FILE_SIZE_MB} MB")
  end
end

#reply?Boolean

Returns is there a reply?.

Returns:

  • (Boolean)

    is there a reply?



109
110
111
# File 'app/models/message.rb', line 109

def reply?
  @reply || false
end

#total_upload_sizeObject (private)



115
116
117
118
119
# File 'app/models/message.rb', line 115

def total_upload_size
  return 0 if uploads.blank?

  uploads.sum(&:size)
end

#total_upload_size_validationObject (private)



121
122
123
124
125
# File 'app/models/message.rb', line 121

def total_upload_size_validation
  return unless total_upload_size > MAX_TOTAL_FILE_SIZE_MB.megabytes

  errors.add(:base, "Total size of uploads exceeds #{MAX_TOTAL_FILE_SIZE_MB} MB")
end