Skip to content

Instantly share code, notes, and snippets.

@remvee
Created March 1, 2013 12:17
Show Gist options
  • Select an option

  • Save remvee/5064263 to your computer and use it in GitHub Desktop.

Select an option

Save remvee/5064263 to your computer and use it in GitHub Desktop.
require "ostruct"
require "active_support/concern"
require "active_model/validations"
require "active_model/errors"
# Soft validations are based on ActiveModel::Validations but don't
# block saving a record.
#
# class Person < ActiveRecord::Base
# include SoftValidations
# validates_softly :name, format: /^[A-Z]/
# end
#
# person = Person.new(name: "fred")
# person.valid? # => true
# person.complete? # => false
# person.warnings.full_message # ["Name is invalid"]
# person.save # => true
module SoftValidations
extend ActiveSupport::Concern
included do |other|
@soft = Class.new(OpenStruct) do
include ActiveModel::Validations
def self.name
@parent.name
end
def self.i18n_scope
@parent.i18n_scope
end
end
@soft.instance_variable_set("@parent", other)
end
module ClassMethods
# Like ActiveModel::Validations#validates.
def validates_softly(*args, &block)
@soft.validates(*args, &block)
end
def soft_class
@soft
end
end
# Run the soft validations on the object and return false when any
# of them fail. Failure are added to the warnings collection.
def complete?
obj = self.class.soft_class.new(attributes)
obj.valid?.tap do
@warnings = obj.errors
end
end
# Returns a collection of warnings as an instance of
# ActiveModel::Errors. This collection is populated by the
# complete? method.
def warnings
@warnings || ActiveModel::Errors.new(self.class.soft_class.new)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment