Reputation: 2364
I have this Rails 6.1 model:
class BankAccount < ApplicationRecord
belongs_to :donor
before_validation -> {
puts #AccAuth: #{account_authorization}"
}
validates :account_authorization, acceptance: { accept: [true, 'true', '1'] }
end
The attribute "account_authorization" doesn't exist in the database, is not a SQL column, is a field from a JSON payload and must be one of the values in the array to be sure the bank answered successfully.
I'm trying to test in my Rspec file like:
let(:invalid_bank_account) do
Fabricate.build(:bank_account, account_authorization: nil, donor: Fabricate(:donor))
end
it 'is not valid record without a truty account_authorization value' do
puts "valid? #{invalid_bank_account.valid?}"
expect(invalid_bank_account).not_to be_valid
end
The result is:
### bank_account.rb >> AccAuth
>> nil
### bank_account_spec.rb >> valid?
>> true
Failure/Error: expect(invalid_bank_account).not_to be_valid
The validation is always successful even if there is no "account_authorization" value in the Model initializer. I'm validating a non-SQL attribute in the correct way?
Upvotes: 1
Views: 77
Reputation: 1078
I like Alex's answer for how to use the acceptance
validator in your situation. However, you could also use the Rails inclusion validator if you'd prefer. I find it a bit clearer and cleaner:
validates :account_authorization, inclusion: { in: [true, 'true', '1'] }
Also, double check to see if you also want to allow the integer one (not just the string) as valid.
To set the verbiage for the validation failure message, you can set it explicitly as mentioned in the docs, or better, put it in the locale file:
#config/locales/en.yml
en:
errors:
format: "%{message}"
header: 'The form entry has errors; please correct the errors below and re-submit.'
messages:
accepted: "The %{attribute} was not accepted; please accept the %{attribute}."
inclusion: "The chosen %{attribute} is not available; please choose an available option." # Rails 4-
inclusion_of: "The chosen %{attribute} is not available; please choose an available option." # Rails 5+
Above copied from my more complete example here: https://stackoverflow.com/a/73837042/14837782
Upvotes: 1
Reputation: 30036
If attribute is nil
it is ignored:
...This check is performed only if terms_of_service is not
nil
.
You have to specifically disallow nil
:
class Account < ApplicationRecord
validates :account_authorization, acceptance: {allow_nil: false}
end
>> Account.new(account_authorization: nil).valid?
=> false
>> Account.new(account_authorization: "1").valid?
=> true
Note, that this will force you to supply account_authorization
value every time you're making an update.
Upvotes: 5