Commit d8c66f44 authored by Igor Drozdov's avatar Igor Drozdov

Handle Rails 6.1 ActiveModel::Errors changes

Modal errors as objects are introduced:
https://github.com/rails/rails/pull/32313

model.errors.first returns ActiveModel::Error object
that's why model.errors.first[1] doesn't work in Rails 6.1

We need a way that works both for 6.1 and 6.0 in order to
introduce changes gradually:

model.errors.values.first works for both versions.

Even though treating errors as a hash is deprecated it works
so we can introduce the changes in 6.0 and then fix the
deprecations when we're on 6.1

(cherry picked from commit b5ecc309314429040921233d4a6216655fede089)
parent 2376a5ee
......@@ -393,7 +393,7 @@ module ApplicationSettingsHelper
end
def integration_expanded?(substring)
@application_setting.errors.any? { |k| k.to_s.start_with?(substring) }
@application_setting.errors.messages.any? { |k, _| k.to_s.start_with?(substring) }
end
def instance_clusters_enabled?
......
......@@ -124,7 +124,9 @@ module Routable
def set_path_errors
route_path_errors = self.errors.delete(:"route.path")
self.errors[:path].concat(route_path_errors) if route_path_errors
route_path_errors&.each do |msg|
self.errors.add(:path, msg)
end
end
def full_name_changed?
......
......@@ -1414,7 +1414,9 @@ class User < ApplicationRecord
if namespace_path_errors.include?('has already been taken') && !User.exists?(username: username)
self.errors.add(:base, :username_exists_as_a_different_namespace)
else
self.errors[:username].concat(namespace_path_errors)
namespace_path_errors.each do |msg|
self.errors.add(:username, msg)
end
end
end
......
......@@ -62,7 +62,7 @@ class FileSizeValidator < ActiveModel::EachValidator
default_message = options[MESSAGES[key]]
errors_options[:message] ||= default_message if default_message
record.errors.add(attribute, MESSAGES[key], errors_options)
record.errors.add(attribute, MESSAGES[key], **errors_options)
end
end
......
......@@ -74,7 +74,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
it 'adds an informative error to the pipeline' do
perform
expect(pipeline.errors.messages).to include(base: ['Pipeline has too many deployments! Requested 2, but the limit is 1.'])
expect(pipeline.errors.added?(:base, 'Pipeline has too many deployments! Requested 2, but the limit is 1.')).to be true
end
it 'increments the error metric' do
......
......@@ -56,8 +56,7 @@ RSpec.shared_examples 'ChronicDurationAttribute writer' do
subject.send("#{virtual_field}=", '-10m')
expect(subject.valid?).to be_falsey
expect(subject.errors&.messages)
.to include(base: ['Maximum job timeout has a value which could not be accepted'])
expect(subject.errors.added?(:base, 'Maximum job timeout has a value which could not be accepted')).to be true
end
end
......
......@@ -38,7 +38,7 @@ RSpec.describe CustomEmoji do
new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace, group: group)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to include(name: ["has already been taken"])
expect(new_emoji.errors.messages).to eq(creator: ["can't be blank"], name: ["has already been taken"])
end
it 'disallows non http and https file value' do
......
......@@ -579,7 +579,9 @@ RSpec.describe Group do
it "is false if avatar is html page" do
group.update_attribute(:avatar, 'uploads/avatar.html')
expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp"])
group.avatar_type
expect(group.errors.added?(:avatar, "file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp")).to be true
end
end
......
......@@ -23,7 +23,7 @@ RSpec.describe MergeRequestDiff do
expect(subject.valid?).to be false
expect(subject.errors.count).to eq 3
expect(subject.errors).to all(include('is not a valid SHA'))
expect(subject.errors.full_messages).to all(include('is not a valid SHA'))
end
it 'does not validate uniqueness by default' do
......
......@@ -1277,7 +1277,9 @@ RSpec.describe Project, factory_default: :keep do
it 'is false if avatar is html page' do
project.update_attribute(:avatar, 'uploads/avatar.html')
expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
project.avatar_type
expect(project.errors.added?(:avatar, "file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp")).to be true
end
end
......
......@@ -2526,8 +2526,9 @@ RSpec.describe User do
it 'is false if avatar is html page' do
user.update_attribute(:avatar, 'uploads/avatar.html')
user.avatar_type
expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
expect(user.errors.added?(:avatar, "file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp")).to be true
end
end
......
......@@ -173,7 +173,7 @@ RSpec.describe Notes::BuildService do
let(:user) { create(:user) }
it 'returns `Discussion to reply to cannot be found` error' do
expect(new_note.errors.first).to include("Discussion to reply to cannot be found")
expect(new_note.errors.added?(:base, "Discussion to reply to cannot be found")).to be true
end
end
end
......
......@@ -19,18 +19,20 @@ RSpec.describe AddressableUrlValidator do
it 'returns error when url is nil' do
expect(validator.validate_each(badge, :link_url, nil)).to be_falsey
expect(badge.errors.first[1]).to eq validator.options.fetch(:message)
expect(badge.errors.added?(:link_url, validator.options.fetch(:message))).to be true
end
it 'returns error when url is empty' do
expect(validator.validate_each(badge, :link_url, '')).to be_falsey
expect(badge.errors.first[1]).to eq validator.options.fetch(:message)
expect(badge.errors.added?(:link_url, validator.options.fetch(:message))).to be true
end
it 'does not allow urls with CR or LF characters' do
aggregate_failures do
urls_with_CRLF.each do |url|
expect(validator.validate_each(badge, :link_url, url)[0]).to eq 'is blocked: URI is invalid'
validator.validate_each(badge, :link_url, url)
expect(badge.errors.added?(:link_url, 'is blocked: URI is invalid')).to be true
end
end
end
......@@ -113,7 +115,7 @@ RSpec.describe AddressableUrlValidator do
it 'does block nil url with provided error message' do
expect(validator.validate_each(badge, :link_url, nil)).to be_falsey
expect(badge.errors.first[1]).to eq message
expect(badge.errors.added?(:link_url, message)).to be true
end
end
......@@ -126,7 +128,7 @@ RSpec.describe AddressableUrlValidator do
subject
expect(badge.errors.first[1]).to eq 'is not allowed due to: Only allowed schemes are http, https'
expect(badge.errors.added?(:link_url, 'is not allowed due to: Only allowed schemes are http, https')).to be true
end
end
......
......@@ -49,7 +49,7 @@ RSpec.describe ArrayMembersValidator do
object = test_class.new(children: [])
expect(object.valid?).to be_falsey
expect(object.errors.messages).to eql(children: ['should be an array of children objects'])
expect(object.errors.messages).to eq(children: ['should be an array of children objects'])
end
end
......@@ -62,7 +62,7 @@ RSpec.describe ArrayMembersValidator do
object = test_class.new(children: [])
expect(object.valid?).to be_falsey
expect(object.errors.messages).to eql(children: ['should be an array of test objects'])
expect(object.errors.messages).to eq(children: ['should be an array of test objects'])
end
end
end
......
......@@ -23,7 +23,7 @@ RSpec.describe DeviseEmailValidator do
subject
expect(user.errors).to be_present
expect(user.errors.first[1]).to eq 'is invalid'
expect(user.errors.added?(:public_email)).to be true
end
it 'returns error when email is nil' do
......@@ -40,7 +40,7 @@ RSpec.describe DeviseEmailValidator do
subject
expect(user.errors).to be_present
expect(user.errors.first[1]).to eq 'is invalid'
expect(user.errors.added?(:public_email)).to be true
end
end
end
......
......@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Utils::ZoomUrlValidator do
expect(zoom_meeting.valid?).to eq(false)
expect(zoom_meeting.errors).to be_present
expect(zoom_meeting.errors.first[1]).to eq 'must contain one valid Zoom URL'
expect(zoom_meeting.errors.added?(:url, 'must contain one valid Zoom URL')).to be true
end
end
......
......@@ -52,7 +52,7 @@ RSpec.describe QualifiedDomainArrayValidator do
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq('entries cannot be nil')
expect(record.errors.added?(:domain_array, "entries cannot be nil")).to be true
end
it 'allows when domain is valid' do
......@@ -67,7 +67,7 @@ RSpec.describe QualifiedDomainArrayValidator do
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'unicode domains should use IDNA encoding'
expect(record.errors.added?(:domain_array, 'unicode domains should use IDNA encoding')).to be true
end
it 'returns error when entry is larger than 255 chars' do
......@@ -76,7 +76,7 @@ RSpec.describe QualifiedDomainArrayValidator do
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'entries cannot be larger than 255 characters'
expect(record.errors.added?(:domain_array, 'entries cannot be larger than 255 characters')).to be true
end
it 'returns error when entry contains HTML tags' do
......@@ -85,7 +85,7 @@ RSpec.describe QualifiedDomainArrayValidator do
subject
expect(record.errors).to be_present
expect(record.errors.first[1]).to eq 'entries cannot contain HTML tags'
expect(record.errors.added?(:domain_array, 'entries cannot contain HTML tags')).to be true
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment