Skip to content

Instantly share code, notes, and snippets.

@carlosramireziii
Last active April 10, 2024 11:11
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save carlosramireziii/73f2c7b12dd6716482e41a3cd8e0a94d to your computer and use it in GitHub Desktop.
Save carlosramireziii/73f2c7b12dd6716482e41a3cd8e0a94d to your computer and use it in GitHub Desktop.
A validator and RSpec matcher for requiring an attachment using Active Storage
class AttachedValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add(attribute, :attached, options) unless value.attached?
end
end
en:
activerecord:
errors:
messages:
attached: is not attached
require "rspec/expectations"
RSpec::Matchers.define :validate_attachment_of do |attr_name|
match do |record|
matcher.matches?(record, attr_name)
end
chain :on do |validation_context|
matcher.on(validation_context)
end
chain :with_message do |message|
matcher.with_message(message)
end
private
def matcher
@matcher ||= ValidateAttachmentOfMatcher.new
end
class ValidateAttachmentOfMatcher
def on(validation_context)
@validation_context = validation_context
end
def with_message(message)
@message = message
end
def matches?(record, attr_name)
record.send(attr_name).purge
record.valid?(validation_context)
record.errors[attr_name].include? message
end
private
attr_reader :validation_context
def message
@message || I18n.translate("activerecord.errors.messages.attached")
end
end
end
@rubendinho
Copy link

Thanks for putting this together. This has worked great for me in Rails 5.2. In Rails 6, you will get an FrozenError: can't modify frozen Hash error from line 32. Instead of purging, the blob should be set to nil.

To fix, that line should be replaced with:

record.send("#{attr_name}=", nil)

An explanation here: rails/rails#37069

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