Skip to content

Instantly share code, notes, and snippets.

@mcmire
Last active July 11, 2019 04:44
Show Gist options
  • Save mcmire/c87dc92729be797ed81de24ab6aa4ecf to your computer and use it in GitHub Desktop.
Save mcmire/c87dc92729be797ed81de24ab6aa4ecf to your computer and use it in GitHub Desktop.
validate_not_nil matcher (sketch)

You can use this matcher like so:

RSpec.describe User, type: :model do
  it { is_expected.to validate_not_nil(:favorite_numbers) }
end
# do this, or just uncomment the line that requires support files
require_relative 'support/matchers/validate_not_nil_matcher'
RSpec.configure do |config|
config.include Matchers, type: :model
end
# spec/support/matchers/validate_not_nil_matcher.rb
module Matchers
def validate_not_nil(attribute_name)
ValidateNotNilMatcher.new(attribute_name)
end
class ValidateNotNilMatcher
def initialize(attribute_name)
@attribute_name = attribute_name
@submatchers = [
disallow_value(nil).for(attribute_name),
allow_value([]).for(attribute_name),
allow_value(["something"]).for(attribute_name)
]
end
def matches?(record)
@record = record
first_failing_submatcher.nil?
end
def does_not_match?(record)
@record = record
first_passing_submatcher.nil?
end
def failure_message
first_failing_submatcher.failure_message
end
def failure_message_when_negated
first_passing_submatcher.failure_message_when_negated
end
private
attr_reader :attribute_name, :submatchers, :record
def allow_value(value)
# Using this class like this is the same as using the `allow_value` matcher.
Shoulda::Matchers::ActiveModel::AllowValueMatcher.new(value)
end
def disallow_value(value)
# The gem doesn't ship with a `disallow_value` matcher, but it does have a
# complement to AllowValueMatcher which such a matcher would probably use,
# if it did exist. Technically this is a private API, but I don't plan on
# removing this any time soon.
Shoulda::Matchers::ActiveModel::DisallowValueMatcher.new(value)
end
def first_failing_submatcher
@first_failing_submatcher ||= submatchers.find do |submatcher|
!submatcher.matches?(record)
end
end
def first_passing_submatcher
@first_passing_submatcher ||= submatchers.find do |submatcher|
!submatcher.does_not_match?(record)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment