Skip to content

validate_presence_of(:active_storage_field) throws exception #1224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ def disallows_original_or_typecast_value?(value)
def disallowed_values
if collection?
[Array.new]
elsif attachment?
[nil]
else
values = []

Expand Down Expand Up @@ -341,6 +343,11 @@ def association_reflection
model.reflect_on_association(@attribute)
end

def attachment?
model.respond_to?(:reflect_on_association) &&
model_has_associations?(["#{@attribute}_attachment", "#{@attribute}_attachments"])
end

def attribute_type
if model.respond_to?(:attribute_types)
model.attribute_types[@attribute.to_s]
Expand All @@ -349,6 +356,10 @@ def attribute_type
end
end

def model_has_associations?(associations)
associations.any? { |association| !!model.reflect_on_association(association) }
end

def presence_validation_exists_on_attribute?
model._validators.include?(@attribute)
end
Expand Down
4 changes: 4 additions & 0 deletions spec/support/unit/helpers/active_record_versions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@ def active_record_supports_optional_for_associations?
def active_record_supports_expression_indexes?
active_record_version >= 5
end

def active_record_supports_validate_presence_on_active_storage?
active_record_version >= '6.0.0.beta1'
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,88 @@ def model_creator
end
end

if active_record_supports_validate_presence_on_active_storage?
context 'a has_one_attached association with a presence validation' do
it 'requires the attribute to be set' do
expect(has_one_attached_child(presence: true)).to validate_presence_of(:child)
end

it_supports(
'ignoring_interference_by_writer',
tests: {
accept_if_qualified_but_changing_value_does_not_interfere: {
changing_values_with: :nil_to_blank
},
reject_if_qualified_but_changing_value_interferes: {
model_name: 'Example',
attribute_name: :attr,
changing_values_with: :never_falsy,
expected_message: <<-MESSAGE
Expected Example to validate that :attr cannot be empty/falsy, but this
could not be proved.
After setting :attr to ‹nil› -- which was read back as ‹"dummy value"›
-- the matcher expected the Example to be invalid, but it was valid
instead.

As indicated in the message above, :attr seems to be changing certain
values as they are set, and this could have something to do with why
this test is failing. If you've overridden the writer method for this
attribute, then you may need to change it to make this test pass, or
do something else entirely.
MESSAGE
}
}
)
end

context 'a has_one_attached association without a presence validation' do
it 'requires the attribute to be set' do
expect(has_one_attached_child(presence: false)).
not_to validate_presence_of(:child)
end
end

context 'a has_many_attached association with a presence validation' do
it 'requires the attribute to be set' do
expect(has_many_attached_children(presence: true)).to validate_presence_of(:children)
end

it_supports(
'ignoring_interference_by_writer',
tests: {
accept_if_qualified_but_changing_value_does_not_interfere: {
changing_values_with: :nil_to_blank
},
reject_if_qualified_but_changing_value_interferes: {
model_name: 'Example',
attribute_name: :attr,
changing_values_with: :never_falsy,
expected_message: <<-MESSAGE
Expected Example to validate that :attr cannot be empty/falsy, but this
could not be proved.
After setting :attr to ‹nil› -- which was read back as ‹"dummy value"›
-- the matcher expected the Example to be invalid, but it was valid
instead.

As indicated in the message above, :attr seems to be changing certain
values as they are set, and this could have something to do with why
this test is failing. If you've overridden the writer method for this
attribute, then you may need to change it to make this test pass, or
do something else entirely.
MESSAGE
}
}
)
end

context 'a has_many_attached association without a presence validation' do
it 'does not require the attribute to be set' do
expect(has_many_attached_children(presence: false)).
not_to validate_presence_of(:children)
end
end
end

context 'a has_many association with a presence validation' do
it 'requires the attribute to be set' do
expect(has_many_children(presence: true)).to validate_presence_of(:children)
Expand Down Expand Up @@ -960,6 +1042,26 @@ def has_many_children(options = {})
end.new
end

def has_one_attached_child(options = {})
define_model :child
define_model :parent do
has_one_attached :child
if options[:presence]
validates_presence_of :child
end
end.new
end

def has_many_attached_children(options = {})
define_model :child
define_model :parent do
has_many_attached :children
if options[:presence]
validates_presence_of :children
end
end.new
end

def active_resource_model
define_active_resource_class :foo, attr: :string do
validates_presence_of :attr
Expand Down