Module: SoftValidation

Extended by:
ActiveSupport::Concern
Included in:
AssertedDistribution, BiologicalAssociation, CharacterState, CollectingEvent, CollectionObject, CollectionProfile, Container, Descriptor, Document, Documentation, Identifier::Global, Image, Loan, Otu, RangedLotCategory, Serial, Source, 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

- (Nil) clear_soft_validations

Returns:

  • (Nil)


203
204
205
# File 'lib/soft_validation.rb', line 203

def clear_soft_validations
  @soft_validation_result = nil
end

- (Boolean) fix_soft_validations(scope = :automatic)

Parameters:

  • scope (Symbol) (defaults to: :automatic)

Returns:

  • (Boolean)


233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/soft_validation.rb', line 233

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)


261
262
263
# File 'lib/soft_validation.rb', line 261

def soft_fixed?
  soft_validations.fixes_run?
end

- (Boolean) soft_valid?

Returns:

  • (Boolean)


266
267
268
# File 'lib/soft_validation.rb', line 266

def soft_valid?
  soft_validations.complete?
end

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

Returns always true

Parameters:

  • set (Symbol) (defaults to: :all)

    the set of soft validations to run

  • ancestors (Boolean)

    whether to also validate ancestors soft validations

Returns:

  • (Boolean)

    always true



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/soft_validation.rb', line 210

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)


256
257
258
# File 'lib/soft_validation.rb', line 256

def soft_validated?
  soft_validations.validated?
end

- (SoftValidations) soft_validations

Returns:



198
199
200
# File 'lib/soft_validation.rb', line 198

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