Skip to content

Instantly share code, notes, and snippets.

@harssh
Created February 28, 2024 20:40
Show Gist options
  • Save harssh/a03af18bce82a0103b3c80e60cefcf32 to your computer and use it in GitHub Desktop.
Save harssh/a03af18bce82a0103b3c80e60cefcf32 to your computer and use it in GitHub Desktop.
warning.rb
# Define a "warnings" validation bucket on ActiveRecord objects.
#
# @example
#
# class MyObject < ActiveRecord::Base
# warning do |vehicle_asset|
# unless vehicle_asset.description == 'bob'
# vehicle_asset.warnings.add(:description, "should be 'bob'")
# end
# end
# end
#
# THEN:
#
# my_object = MyObject.new
# my_object.description = 'Fred'
# my_object.sensible? # => false
# my_object.warnings.full_messages # => ["Description should be 'bob'"]
module Warnings
module Validations
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
define_callbacks :warning
end
module ClassMethods
def warning(*args, &block)
options = args.extract_options!
if options.key?(:on)
options = options.dup
options[:if] = Array.wrap(options[:if])
options[:if] << "validation_context == :#{options[:on]}"
end
args << options
set_callback(:warning, *args, &block)
end
end
# Similar to ActiveModel::Validations#valid? but for warnings
def sensible?
warnings.clear
run_callbacks :warning
warnings.empty?
end
# Similar to ActiveModel::Validations#errors but returns a warnings collection
def warnings
@warnings ||= ActiveModel::Errors.new(self)
end
end
end
ActiveRecord::Base.send(:include, Warnings::Validations)
@harssh
Copy link
Author

harssh commented Mar 7, 2024

class MyModelWarnings < SimpleDelegator
  include ActiveModel::Validations

  validates :name, presence: true

  def initialize(model)
    super
    validate
  end  

  def warnings; errors; end
end

class MyModel < ActiveRecord::Base
  def warnings
    @warnings ||= MyModelWarnings.new(self).warnings
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment