DEPRECATION WARNING: Calling `<<` to an ActiveModel::Errors message array in order to add an error is deprecated. in ruby

2.1k Views Asked by At

Ruby - 2.7.3 Rails - 6.1.3.2

DEPRECATION WARNING: Calling << to an ActiveModel::Errors message array in order to add an error is deprecated. Please callActiveModel::Errors#add instead. (called from validate at /var/home/application_name/app/models/contacts.rb:4)

1.class AssociatedProgramValidator < ActiveModel::Validator
2.  def validate(record)
3.    unless record.user.programs.pluck(:name).include? record.program_name
4.      record.errors[:program_id] << "No #{record.program_name} found on user"
5.    end
6.  end
7.end
8.
9.class Contacts < ApplicationRecord
10.
11.  include ActiveModel::Validations
12.end

Please give some suggestion.

3

There are 3 best solutions below

0
stolarz On BEST ANSWER

I suspect it should be:

record.errors.add(:program_id, message: "No #{record.program_name} found on user")

https://api.rubyonrails.org/v6.1.3/classes/ActiveModel/Errors.html#method-i-add

2
Ardena On

In testing, it looks like the actual equivalent is

record.errors.add(:program_id, "No #{record.program_name} found on user")

I suspect the use of "message" instead of using it as an error type might be a better idea, but your code may not handle the difference without adjustment.

0
notapatch On

Errors were changed from a hash to an object by work by lulalala for Rails 6.1. And the following is taken from their comprehensive blog post on it.

Avoid modifying the hashes directly

In the past you can add new errors by appending messages directly on to the hash:

book.errors[:title] << 'is not interesting enough.'
book.errors[:title].clear

This would now also raise a deprecation warning, because it is no longer the source of truth, but generated from the Error objects when called. Instead always use the add interface, or enumeration methods:

book.errors.add(:title, 'is not interesting enough.')
book.errors.delete_all { |error| error.type == :too_long }

Manipulating the following will have no effect:

  • errors itself as a hash (e.g. errors[:foo] = 'bar')
  • the hash returned by errors#messages (e.g. errors.messages[:foo] = 'bar')
  • the hash returned by errors#details (e.g. errors.details[:foo].clear)