Module: SoftValidation

Extended by:
ActiveSupport::Concern
Included in:
AssertedDistribution, BiologicalAssociation, CharacterState, CollectingEvent, CollectionObject, CollectionProfile, Container, Descriptor, Document, Documentation, Image, Loan, Otu, RangedLotCategory, Serial, Source::Bibtex, TaxonName, TaxonNameClassification, TaxonNameRelationship, TypeMaterial
Defined in:
lib/soft_validation.rb,
lib/soft_validation/soft_validation.rb,
lib/soft_validation/soft_validations.rb,
lib/soft_validation/soft_validation_method.rb

Overview

Vaguely inspired by concepts from by svn://rubyforge.org/var/svn/softvalidations, but not as elegant.

Soft validations are a means to tie warnings or suggestions to instances of data. Soft validations do not prevent an instance from being saved. They are not intended to be bound to AR callbacks, but this may be possible. They may be used to alert the user to data issues that need to be addressed, or alert the programmer who is batch parsing data as to the quality of the incoming data, etc..

For example, soft validations could be shown on #show controller methods.

Usage:

class Foo < ApplicationRecord
  include SoftValidation
  soft_validate(:a_soft_validation_method )

  # Validations can be assigned to a set (only one), and validations in a set
  # can be called individually.
  soft_validate(:other_soft_validation_method, set: :some_set)
  soft_validate(:yet_another_method, set: :some_other_set )
  soft_validate(:a_third_method, resolution: [:route_name, route_name2])

  $hungry = true

  def a_soft_validation_method
    soft_validations.add(:base, 'hungry!',                          # :base or a model attribute (column)
      fix: :cook_cheezburgers,
      success_message: 'no longer hungry, cooked a cheezeburger',
      failure_message: 'oh no, cat ate your cheezeburger'
    ) if $hungry
  end

  def cook_cheezburgers
    $hungry = false
  end
end

f = Foo.new

f.soft_validations.validated?             # => false
f.soft_validations.fixes_run?             # => false
f.soft_validations.fixed?                 # => false
f.soft_validations.complete?              # => false

f.soft_validate                           # => true
f.soft_validated?                         # => true
f.soft_fixed?                             # => false
f.soft_valid?                             # => false  # true if there are no SoftValidations produced

f.soft_validations.soft_validations                        # => [soft_validation, soft_validation1 ... ]
f.soft_validations.soft_validations.size                   # => 1
f.soft_validations.soft_validations.first                  # => A SoftValidation instance

# SoftValidation attributes
f.soft_validations.soft_validations.first.attribute          # => :base
f.soft_validations.soft_validations.first.message            # => 'hungry!'
f.soft_validations.soft_validations.first.success_message    # => 'no longer hungry, cooked a cheezeburger'
f.soft_validations.soft_validations.first.failure_message    # => 'oh no, cat ate your cheezeburger'

f.soft_validations.soft_validations.first.fixed?           # => false
f.soft_validations.soft_validations.first.result_message     # => 'fix not yet run'

f.fix_soft_validations                    # => true
f.soft_fixed?                             # => true
f.soft_valid?                             # => false !! There is still a SoftValidation generated, will be true next time it's run

f.soft_validations.fixes_run                               # => true
f.soft_validations.soft_validations.first.fixed?           # => true
f.soft_validations.soft_validations.first.result_message   # => 'no longer hungry, cooked a cheezeburger'
f.soft_validations.on(:base)               # => [soft_validation, ... ]
f.soft_validations.messages                # => ['hungry!']
f.soft_validations.messages_on(:base)      # => ['hungry!']

f.clear_soft_validations

f.soft_validate(:some_other_set)          # only run this set of validations

Defined Under Namespace

Modules: ClassMethods Classes: SoftValidation, SoftValidationError, SoftValidationMethod, SoftValidations

Constant Summary

ANCESTORS_WITH_SOFT_VALIDATIONS =
Hash.new do |h, klass|
  h[klass.name] = (klass.ancestors.select {|a| a.respond_to?(:soft_validates?) && a.soft_validates?} - [klass]) # a < ApplicationRecord && would be faster but requires AR in spec
end

Instance Method Summary (collapse)

Instance Method Details

- (Object) clear_soft_validations



193
194
195
# File 'lib/soft_validation.rb', line 193

def clear_soft_validations
  @soft_validation_result = nil
end

- (Object) fix_soft_validations(scope = :automatic)



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/soft_validation.rb', line 221

def fix_soft_validations(scope = :automatic)
  return false if !soft_validated?
  raise 'invalid scope passed to fix_soft_validations' if ![:all, :automatic, :requested].include?(scope)
  soft_validations.soft_validations.each do |v|
    if v.fix
      if v.fix_trigger == scope
        if self.send(v.fix)
          v.fixed = :fixed
        else
          v.fixed = :fix_error
        end
      else
        v.fixed = :fix_not_triggered
      end
    else
      v.fixed = :no_fix_available
    end
  end
  soft_validations.fixes_run = scope
  true
end

- (Boolean) soft_fixed?

Returns:

  • (Boolean)


247
248
249
# File 'lib/soft_validation.rb', line 247

def soft_fixed?
  soft_validations.fixes_run?
end

- (Boolean) soft_valid?

Returns:

  • (Boolean)


251
252
253
# File 'lib/soft_validation.rb', line 251

def soft_valid?
  soft_validations.complete?
end

- (True) soft_validate(set = :all, include_ancestors = true)

Parameters:

  • the (:set, Symbol)

    set of soft validations to run

  • whether (:ancestors, Boolean)

    to also validate ancestors soft validations

Returns:

  • (True)


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/soft_validation.rb', line 200

def soft_validate(set = :all, include_ancestors = true)
  clear_soft_validations
  soft_validations
  sets = case set.class.name
         when 'Array'
           set
         when 'Symbol'
           [set]
         when 'String'
           [set.to_sym]
         end

  sets.each do |s|
    self.class.soft_validators(set: s, include_ancestors: include_ancestors).each do |m|
      self.send(m)
    end
  end
  soft_validations.validated = true
  true
end

- (Boolean) soft_validated?

Returns:

  • (Boolean)


243
244
245
# File 'lib/soft_validation.rb', line 243

def soft_validated?
  soft_validations.validated?
end

- (Object) soft_validations

instance methods



189
190
191
# File 'lib/soft_validation.rb', line 189

def soft_validations
  @soft_validation_result ||= SoftValidations.new(self)
end