Revert typography change in user facing errors

This change would force a lot of existing applications and libraries
to update their tests.

We included it in the beta to collect feedback from the community and
we had some comments about how negative this change would be.

Developers that care about the typography of their error messages
can easily change it in their applications using the translation
files, so there is no need to inflict pain in the upgrade process
by changing the default in the framework.

Revert "Merge PR #45463"

This reverts commit 9f60cd8dc7, reversing
changes made to 35d574dbfd.
This commit is contained in:
Rafael Mendonça França 2023-09-26 21:45:03 +00:00
parent 99cf11cca4
commit acfa045405
No known key found for this signature in database
GPG Key ID: FC23B6D0F1EEE948
31 changed files with 96 additions and 90 deletions

View File

@ -1347,7 +1347,7 @@ class RenderTest < ActionController::TestCase
get :partial_with_form_builder_and_invalid_model
assert_equal <<~HTML.strip, @response.body.strip
<div class="field_with_errors"><label for="post_title">Title</label> <span class="error">cant be blank</span></div>
<div class="field_with_errors"><label for="post_title">Title</label> <span class="error">can&#39;t be blank</span></div>
HTML
ensure
ActionView::Base.field_error_proc = old_proc if old_proc

View File

@ -20,7 +20,7 @@ class ActiveModelHelperTest < ActionView::TestCase
super
@post = Post.new
@post.errors.add(:author_name, "cant be empty")
@post.errors.add(:author_name, "can't be empty")
@post.errors.add(:body, "foo")
@post.errors.add(:category, "must exist")
@post.errors.add(:published, "must be accepted")
@ -163,7 +163,7 @@ class ActiveModelHelperTest < ActionView::TestCase
end
assert_dom_equal(
%(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /> <span class="error">cant be empty</span></div>),
%(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /> <span class="error">can't be empty</span></div>),
text_field("post", "author_name")
)
ensure

View File

@ -276,10 +276,10 @@ class FormWithActsLikeFormForTest < FormWithTest
@comment = Comment.new
def @post.errors
Class.new {
def [](field); field == "author_name" ? ["cant be empty"] : [] end
def [](field); field == "author_name" ? ["can't be empty"] : [] end
def empty?() false end
def count() 1 end
def full_messages() ["Author name cant be empty"] end
def full_messages() ["Author name can't be empty"] end
}.new
end
def @post.to_key; [123]; end

View File

@ -110,10 +110,10 @@ class FormHelperTest < ActionView::TestCase
@comment = Comment.new
def @post.errors
Class.new {
def [](field); field == "author_name" ? ["cant be empty"] : [] end
def [](field); field == "author_name" ? ["can't be empty"] : [] end
def empty?() false end
def count() 1 end
def full_messages() ["Author name cant be empty"] end
def full_messages() ["Author name can't be empty"] end
}.new
end
def @post.to_key; [123]; end

View File

@ -1,3 +1,9 @@
* Remove change in the typography of user facing error messages.
For example, “cant be blank” is again “can't be blank”.
*Rafael Mendonça França*
## Rails 7.1.0.beta1 (September 13, 2023) ##
* Support composite identifiers in `to_key`

View File

@ -284,7 +284,7 @@ module ActiveModel
#
# person.errors.add(:name, :blank)
# person.errors.messages
# # => {:name=>["cant be blank"]}
# # => {:name=>["can't be blank"]}
#
# person.errors.add(:name, :too_long, count: 25)
# person.errors.messages
@ -332,7 +332,7 @@ module ActiveModel
#
# person.errors.add :name, :blank
# person.errors.added? :name, :blank # => true
# person.errors.added? :name, "cant be blank" # => true
# person.errors.added? :name, "can't be blank" # => true
#
# If the error requires options, then it returns +true+ with
# the correct options, or +false+ with incorrect or missing options.
@ -385,7 +385,7 @@ module ActiveModel
#
# person = Person.create(address: '123 First St.')
# person.errors.full_messages
# # => ["Name is too short (minimum is 5 characters)", "Name cant be blank", "Email cant be blank"]
# # => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
def full_messages
@errors.map(&:full_message)
end
@ -400,7 +400,7 @@ module ActiveModel
#
# person = Person.create()
# person.errors.full_messages_for(:name)
# # => ["Name is too short (minimum is 5 characters)", "Name cant be blank"]
# # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
def full_messages_for(attribute)
where(attribute).map(&:full_message).freeze
end
@ -414,7 +414,7 @@ module ActiveModel
#
# person = Person.create()
# person.errors.messages_for(:name)
# # => ["is too short (minimum is 5 characters)", "cant be blank"]
# # => ["is too short (minimum is 5 characters)", "can't be blank"]
def messages_for(attribute)
where(attribute).map(&:message)
end
@ -487,7 +487,7 @@ module ActiveModel
# person = Person.new
# person.name = nil
# person.valid?
# # => ActiveModel::StrictValidationFailed: Name cant be blank
# # => ActiveModel::StrictValidationFailed: Name can't be blank
class StrictValidationFailed < StandardError
end

View File

@ -10,10 +10,10 @@ en:
inclusion: "is not included in the list"
exclusion: "is reserved"
invalid: "is invalid"
confirmation: "doesnt match %{attribute}"
confirmation: "doesn't match %{attribute}"
accepted: "must be accepted"
empty: "cant be empty"
blank: "cant be blank"
empty: "can't be empty"
blank: "can't be blank"
present: "must be blank"
too_long:
one: "is too long (maximum is 1 character)"

View File

@ -57,7 +57,7 @@ module ActiveModel
#
# user.save # => false, password required
# user.password = "vr00m"
# user.save # => false, confirmation doesnt match
# user.save # => false, confirmation doesn't match
# user.password_confirmation = "vr00m"
# user.save # => true
#

View File

@ -326,7 +326,7 @@ module ActiveModel
#
# person = Person.new
# person.valid? # => false
# person.errors # => #<ActiveModel::Errors:0x007fe603816640 @messages={name:["cant be blank"]}>
# person.errors # => #<ActiveModel::Errors:0x007fe603816640 @messages={name:["can't be blank"]}>
def errors
@errors ||= Errors.new(self)
end

View File

@ -64,7 +64,7 @@ module ActiveModel
# validates_presence_of :password_confirmation, if: :password_changed?
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "doesnt match
# * <tt>:message</tt> - A custom error message (default is: "doesn't match
# <tt>%{translated_attribute_name}</tt>").
# * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by
# non-text columns (+true+ by default).

View File

@ -26,7 +26,7 @@ module ActiveModel
# <tt>false.blank? # => true</tt>.
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "cant be blank").
# * <tt>:message</tt> - A custom error message (default is: "can't be blank").
#
# There is also a list of default options supported by every validator:
# +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+.

View File

@ -144,7 +144,7 @@ module ActiveModel
# person = Person.new
# person.name = ''
# person.valid?
# # => ActiveModel::StrictValidationFailed: Name cant be blank
# # => ActiveModel::StrictValidationFailed: Name can't be blank
def validates!(*attributes)
options = attributes.extract_options!
options[:strict] = true

View File

@ -89,7 +89,7 @@ class ErrorTest < ActiveModel::TestCase
test "message with type as a symbol" do
error = ActiveModel::Error.new(Person.new, :name, :blank)
assert_equal "cant be blank", error.message
assert_equal "can't be blank", error.message
end
test "message with custom interpolation" do
@ -178,15 +178,15 @@ class ErrorTest < ActiveModel::TestCase
test "full_message returns the given message with the attribute name included" do
error = ActiveModel::Error.new(Person.new, :name, :blank)
assert_equal "name cant be blank", error.full_message
assert_equal "name can't be blank", error.full_message
end
test "full_message uses default format" do
error = ActiveModel::Error.new(Person.new, :name, message: "cant be blank")
error = ActiveModel::Error.new(Person.new, :name, message: "can't be blank")
# Use a locale without errors.format
I18n.with_locale(:unknown) {
assert_equal "name cant be blank", error.full_message
assert_equal "name can't be blank", error.full_message
}
end

View File

@ -179,7 +179,7 @@ class ErrorsTest < ActiveModel::TestCase
person.errors.add(:name, :blank)
assert_equal :blank, person.errors.objects.first.type
assert_equal ["cant be blank"], person.errors[:name]
assert_equal ["can't be blank"], person.errors[:name]
end
test "add, with type as String" do
@ -216,7 +216,7 @@ class ErrorsTest < ActiveModel::TestCase
person.errors.add(:name, type)
assert_equal :blank, person.errors.objects.first.type
assert_equal ["cant be blank"], person.errors[:name]
assert_equal ["can't be blank"], person.errors[:name]
end
test "add an error message on a specific attribute with a defined type" do

View File

@ -52,14 +52,14 @@ class SecurePasswordTest < ActiveModel::TestCase
@user.password = ""
assert_not @user.valid?(:create), "user should be invalid"
assert_equal 1, @user.errors.count
assert_equal ["cant be blank"], @user.errors[:password]
assert_equal ["can't be blank"], @user.errors[:password]
end
test "create a new user with validation and a nil password" do
@user.password = nil
assert_not @user.valid?(:create), "user should be invalid"
assert_equal 1, @user.errors.count
assert_equal ["cant be blank"], @user.errors[:password]
assert_equal ["can't be blank"], @user.errors[:password]
end
test "create a new user with validation and password length greater than 72 characters" do
@ -85,7 +85,7 @@ class SecurePasswordTest < ActiveModel::TestCase
@user.password_confirmation = ""
assert_not @user.valid?(:create), "user should be invalid"
assert_equal 1, @user.errors.count
assert_equal ["doesnt match Password"], @user.errors[:password_confirmation]
assert_equal ["doesn't match Password"], @user.errors[:password_confirmation]
end
test "create a new user with validation and a nil password confirmation" do
@ -99,7 +99,7 @@ class SecurePasswordTest < ActiveModel::TestCase
@user.password_confirmation = "something else"
assert_not @user.valid?(:create), "user should be invalid"
assert_equal 1, @user.errors.count
assert_equal ["doesnt match Password"], @user.errors[:password_confirmation]
assert_equal ["doesn't match Password"], @user.errors[:password_confirmation]
end
test "resetting password to nil clears the password cache" do
@ -144,7 +144,7 @@ class SecurePasswordTest < ActiveModel::TestCase
@existing_user.password = nil
assert_not @existing_user.valid?(:update), "user should be invalid"
assert_equal 1, @existing_user.errors.count
assert_equal ["cant be blank"], @existing_user.errors[:password]
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test "updating an existing user with validation and password length greater than 72" do
@ -160,7 +160,7 @@ class SecurePasswordTest < ActiveModel::TestCase
@existing_user.password_confirmation = ""
assert_not @existing_user.valid?(:update), "user should be invalid"
assert_equal 1, @existing_user.errors.count
assert_equal ["doesnt match Password"], @existing_user.errors[:password_confirmation]
assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation]
end
test "updating an existing user with validation and a nil password confirmation" do
@ -174,7 +174,7 @@ class SecurePasswordTest < ActiveModel::TestCase
@existing_user.password_confirmation = "something else"
assert_not @existing_user.valid?(:update), "user should be invalid"
assert_equal 1, @existing_user.errors.count
assert_equal ["doesnt match Password"], @existing_user.errors[:password_confirmation]
assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation]
end
test "updating an existing user with validation and a correct password challenge" do
@ -222,14 +222,14 @@ class SecurePasswordTest < ActiveModel::TestCase
@existing_user.password_digest = ""
assert_not @existing_user.valid?(:update), "user should be invalid"
assert_equal 1, @existing_user.errors.count
assert_equal ["cant be blank"], @existing_user.errors[:password]
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test "updating an existing user with validation and a nil password digest" do
@existing_user.password_digest = nil
assert_not @existing_user.valid?(:update), "user should be invalid"
assert_equal 1, @existing_user.errors.count
assert_equal ["cant be blank"], @existing_user.errors[:password]
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test "setting a blank password should not change an existing password" do

View File

@ -109,12 +109,12 @@ class JsonSerializationTest < ActiveModel::TestCase
test "should return Hash for errors" do
contact = Contact.new
contact.errors.add :name, "cant be blank"
contact.errors.add :name, "can't be blank"
contact.errors.add :name, "is too short (minimum is 2 characters)"
contact.errors.add :age, "must be 16 or over"
hash = {}
hash[:name] = ["cant be blank", "is too short (minimum is 2 characters)"]
hash[:name] = ["can't be blank", "is too short (minimum is 2 characters)"]
hash[:age] = ["must be 16 or over"]
assert_equal hash.to_json, contact.errors.to_json
end

View File

@ -57,7 +57,7 @@ class ConfirmationValidationTest < ActiveModel::TestCase
p.karma_confirmation = "None"
assert_predicate p, :invalid?
assert_equal ["doesnt match Karma"], p.errors[:karma_confirmation]
assert_equal ["doesn't match Karma"], p.errors[:karma_confirmation]
p.karma = "None"
assert_predicate p, :valid?
@ -70,14 +70,14 @@ class ConfirmationValidationTest < ActiveModel::TestCase
I18n.load_path.clear
I18n.backend = I18n::Backend::Simple.new
I18n.backend.store_translations("en",
errors: { messages: { confirmation: "doesnt match %{attribute}" } },
errors: { messages: { confirmation: "doesn't match %{attribute}" } },
activemodel: { attributes: { topic: { title: "Test Title" } } })
Topic.validates_confirmation_of(:title)
t = Topic.new("title" => "We should be confirmed", "title_confirmation" => "")
assert_predicate t, :invalid?
assert_equal ["doesnt match Test Title"], t.errors[:title_confirmation]
assert_equal ["doesn't match Test Title"], t.errors[:title_confirmation]
ensure
I18n.load_path.replace @old_load_path
I18n.backend = @old_backend

View File

@ -39,7 +39,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase
# validates_confirmation_of: generate_message(attr_name, :confirmation, message: custom_message)
def test_generate_message_confirmation_with_default_message
assert_equal "doesnt match Title", @person.errors.generate_message(:title, :confirmation)
assert_equal "doesn't match Title", @person.errors.generate_message(:title, :confirmation)
end
def test_generate_message_confirmation_with_custom_message
@ -57,7 +57,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase
# add_on_empty: generate_message(attr, :empty, message: custom_message)
def test_generate_message_empty_with_default_message
assert_equal "cant be empty", @person.errors.generate_message(:title, :empty)
assert_equal "can't be empty", @person.errors.generate_message(:title, :empty)
end
def test_generate_message_empty_with_custom_message
@ -66,7 +66,7 @@ class I18nGenerateMessageValidationTest < ActiveModel::TestCase
# validates_presence_of: generate_message(attr, :blank, message: custom_message)
def test_generate_message_blank_with_default_message
assert_equal "cant be blank", @person.errors.generate_message(:title, :blank)
assert_equal "can't be blank", @person.errors.generate_message(:title, :blank)
end
def test_generate_message_blank_with_custom_message

View File

@ -67,9 +67,9 @@ class I18nValidationTest < ActiveModel::TestCase
})
person = person_class.new
error = ActiveModel::Error.new(person, :gender, "cant be blank")
error = ActiveModel::Error.new(person, :gender, "can't be blank")
person.errors.import(error, attribute: "person[0].contacts.gender")
assert_equal ["Gender cant be blank"], person.errors.full_messages
assert_equal ["Gender can't be blank"], person.errors.full_messages
end
def test_errors_full_messages_uses_attribute_format

View File

@ -18,14 +18,14 @@ class PresenceValidationTest < ActiveModel::TestCase
t = Topic.new
assert_predicate t, :invalid?
assert_equal ["cant be blank"], t.errors[:title]
assert_equal ["cant be blank"], t.errors[:content]
assert_equal ["can't be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:content]
t.title = "something"
t.content = " "
assert_predicate t, :invalid?
assert_equal ["cant be blank"], t.errors[:content]
assert_equal ["can't be blank"], t.errors[:content]
t.content = "like stuff"
@ -36,8 +36,8 @@ class PresenceValidationTest < ActiveModel::TestCase
Topic.validates_presence_of %w(title content)
t = Topic.new
assert_predicate t, :invalid?
assert_equal ["cant be blank"], t.errors[:title]
assert_equal ["cant be blank"], t.errors[:content]
assert_equal ["can't be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:content]
end
def test_validates_acceptance_of_with_custom_error_using_quotes
@ -53,7 +53,7 @@ class PresenceValidationTest < ActiveModel::TestCase
p = Person.new
assert_predicate p, :invalid?
assert_equal ["cant be blank"], p.errors[:karma]
assert_equal ["can't be blank"], p.errors[:karma]
p.karma = "Cold"
assert_predicate p, :valid?
@ -65,7 +65,7 @@ class PresenceValidationTest < ActiveModel::TestCase
p = CustomReader.new
assert_predicate p, :invalid?
assert_equal ["cant be blank"], p.errors[:karma]
assert_equal ["can't be blank"], p.errors[:karma]
p[:karma] = "Cold"
assert_predicate p, :valid?
@ -79,11 +79,11 @@ class PresenceValidationTest < ActiveModel::TestCase
t.title = ""
assert_predicate t, :invalid?
assert_equal ["cant be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:title]
t.title = " "
assert_predicate t, :invalid?
assert_equal ["cant be blank"], t.errors[:title]
assert_equal ["can't be blank"], t.errors[:title]
t.title = nil
assert_predicate t, :valid?

View File

@ -65,7 +65,7 @@ class ValidatesTest < ActiveModel::TestCase
Person.validates :karma, presence: true, email: { if: :condition_is_false }
person = Person.new
person.valid?
assert_equal ["cant be blank"], person.errors[:karma]
assert_equal ["can't be blank"], person.errors[:karma]
end
def test_validates_with_if_as_shared_conditions
@ -78,7 +78,7 @@ class ValidatesTest < ActiveModel::TestCase
Person.validates :karma, presence: true, email: { unless: :condition_is_true }
person = Person.new
person.valid?
assert_equal ["cant be blank"], person.errors[:karma]
assert_equal ["can't be blank"], person.errors[:karma]
end
def test_validates_with_unless_shared_conditions

View File

@ -64,8 +64,8 @@ class ValidationsTest < ActiveModel::TestCase
def test_errors_on_nested_attributes_expands_name
t = Topic.new
t.errors.add("replies.name", "cant be blank")
assert_equal ["Replies name cant be blank"], t.errors.full_messages
t.errors.add("replies.name", "can't be blank")
assert_equal ["Replies name can't be blank"], t.errors.full_messages
end
def test_errors_on_base
@ -213,8 +213,8 @@ class ValidationsTest < ActiveModel::TestCase
assert_predicate t, :invalid?
hash = {}
hash[:title] = ["cant be blank"]
hash[:content] = ["cant be blank"]
hash[:title] = ["can't be blank"]
hash[:content] = ["can't be blank"]
assert_equal t.errors.to_json, hash.to_json
end
@ -224,7 +224,7 @@ class ValidationsTest < ActiveModel::TestCase
t = Topic.new("title" => "")
assert_predicate t, :invalid?
assert_equal "cant be blank", t.errors["title"].first
assert_equal "can't be blank", t.errors["title"].first
Topic.validates_presence_of :title, :author_name
Topic.validate { errors.add("author_email_address", "will never be valid") }
Topic.validates_length_of :title, :content, minimum: 2
@ -233,10 +233,10 @@ class ValidationsTest < ActiveModel::TestCase
assert_predicate t, :invalid?
assert_equal :title, key = t.errors.attribute_names[0]
assert_equal "cant be blank", t.errors[key][0]
assert_equal "can't be blank", t.errors[key][0]
assert_equal "is too short (minimum is 2 characters)", t.errors[key][1]
assert_equal :author_name, key = t.errors.attribute_names[1]
assert_equal "cant be blank", t.errors[key][0]
assert_equal "can't be blank", t.errors[key][0]
assert_equal :author_email_address, key = t.errors.attribute_names[2]
assert_equal "will never be valid", t.errors[key][0]
assert_equal :content, key = t.errors.attribute_names[3]
@ -414,7 +414,7 @@ class ValidationsTest < ActiveModel::TestCase
exception = assert_raises(ActiveModel::StrictValidationFailed) do
Topic.new.valid?
end
assert_equal "Title cant be blank", exception.message
assert_equal "Title can't be blank", exception.message
end
def test_does_not_modify_options_argument

View File

@ -361,7 +361,7 @@ module ActiveRecord
# end
#
# person.pets.create!(name: nil)
# # => ActiveRecord::RecordInvalid: Validation failed: Name cant be blank
# # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
def create!(attributes = {}, &block)
@association.create!(attributes, &block)
end

View File

@ -2888,7 +2888,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_predicate pirate, :valid?
assert_not pirate.valid?(:conference)
assert_equal "cant be blank", ship.errors[:name].first
assert_equal "can't be blank", ship.errors[:name].first
end
test "association with instance dependent scope" do

View File

@ -536,8 +536,8 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib
assert_not_predicate invalid_electron, :valid?
assert_predicate valid_electron, :valid?
assert_not_predicate molecule, :valid?
assert_equal ["cant be blank"], molecule.errors["electrons[1].name"]
assert_not_equal ["cant be blank"], molecule.errors["electrons.name"]
assert_equal ["can't be blank"], molecule.errors["electrons[1].name"]
assert_not_equal ["can't be blank"], molecule.errors["electrons.name"]
ensure
ActiveRecord.index_nested_attribute_errors = old_attribute_config
end
@ -1525,7 +1525,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
@pirate.ship.name = ""
@pirate.catchphrase = nil
assert_predicate @pirate, :invalid?
assert_equal ["cant be blank", "is invalid"], @pirate.errors[:"ship.name"]
assert_equal ["can't be blank", "is invalid"], @pirate.errors[:"ship.name"]
ensure
Ship._validators = old_validators if old_validators
Ship._validate_callbacks = old_callbacks if old_callbacks
@ -1820,7 +1820,7 @@ module AutosaveAssociationOnACollectionAssociationTests
@pirate.public_send(@association_name).each { |child| child.name = "" }
assert_not_predicate @pirate, :valid?
assert_equal ["cant be blank"], @pirate.errors["#{@association_name}.name"]
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
assert_empty @pirate.errors[@association_name]
end
@ -1828,7 +1828,7 @@ module AutosaveAssociationOnACollectionAssociationTests
@pirate.public_send(@association_name).build(name: "")
assert_not_predicate @pirate, :valid?
assert_equal ["cant be blank"], @pirate.errors["#{@association_name}.name"]
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
assert_empty @pirate.errors[@association_name]
end
@ -1852,7 +1852,7 @@ module AutosaveAssociationOnACollectionAssociationTests
@pirate.catchphrase = nil
assert_not_predicate @pirate, :valid?
assert_equal ["cant be blank"], @pirate.errors["#{@association_name}.name"]
assert_equal ["can't be blank"], @pirate.errors["#{@association_name}.name"]
assert_predicate @pirate.errors[:catchphrase], :any?
end

View File

@ -1134,7 +1134,7 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR
part = ShipPart.new(name: "Stern", ship_attributes: { name: nil })
assert_not_predicate part, :valid?
assert_equal ["Ship name cant be blank"], part.errors.full_messages
assert_equal ["Ship name can't be blank"], part.errors.full_messages
end
end

View File

@ -48,7 +48,7 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
topic = Topic.new
topic.errors.add(:title, :invalid)
topic.errors.add(:title, :blank)
assert_equal "Validation failed: Title is invalid, Title cant be blank", ActiveRecord::RecordInvalid.new(topic).message
assert_equal "Validation failed: Title is invalid, Title can't be blank", ActiveRecord::RecordInvalid.new(topic).message
end
test "RecordInvalid exception translation falls back to the :errors namespace" do

View File

@ -367,7 +367,7 @@ irb> user = User.new
irb> user.save
=> false
irb> user.save!
ActiveRecord::RecordInvalid: Validation failed: Name cant be blank
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
```
You can learn more about validations in the [Active Record Validations

View File

@ -2226,7 +2226,7 @@ to your `Customer` model. If you try to create a new `Customer` without passing
```irb
irb> Customer.find_or_create_by!(first_name: 'Andy')
ActiveRecord::RecordInvalid: Validation failed: Orders count cant be blank
ActiveRecord::RecordInvalid: Validation failed: Orders count can't be blank
```
[`find_or_create_by!`]: https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by-21

View File

@ -205,21 +205,21 @@ irb> p.errors.size
irb> p.valid?
=> false
irb> p.errors.objects.first.full_message
=> "Name cant be blank"
=> "Name can't be blank"
irb> p = Person.create
=> #<Person id: nil, name: nil>
irb> p.errors.objects.first.full_message
=> "Name cant be blank"
=> "Name can't be blank"
irb> p.save
=> false
irb> p.save!
ActiveRecord::RecordInvalid: Validation failed: Name cant be blank
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
irb> Person.create!
ActiveRecord::RecordInvalid: Validation failed: Name cant be blank
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
```
[`invalid?`][] is the inverse of `valid?`. It triggers your validations,
@ -648,7 +648,7 @@ validates :boolean_field_name, exclusion: [nil]
By using one of these validations, you will ensure the value will NOT be `nil`
which would result in a `NULL` value in most cases.
The default error message is _"cant be blank"_.
The default error message is _"can't be blank"_.
[`Object#blank?`]: https://api.rubyonrails.org/classes/Object.html#method-i-blank-3F
@ -1087,7 +1087,7 @@ irb> book.valid?
irb> book.valid?(:ensure_title)
=> false
irb> book.errors.messages
=> {:title=>["cant be blank"]}
=> {:title=>["can't be blank"]}
```
When triggered by an explicit context, validations are run for that context,
@ -1106,7 +1106,7 @@ irb> person = Person.new
irb> person.valid?(:account_setup)
=> false
irb> person.errors.messages
=> {:email=>["has already been taken"], :age=>["is not a number"], :name=>["cant be blank"]}
=> {:email=>["has already been taken"], :age=>["is not a number"], :name=>["can't be blank"]}
```
We will cover more use-cases for `on:` in the [callbacks guide](active_record_callbacks.html).
@ -1125,7 +1125,7 @@ end
```irb
irb> Person.new.valid?
ActiveModel::StrictValidationFailed: Name cant be blank
ActiveModel::StrictValidationFailed: Name can't be blank
```
There is also the ability to pass a custom exception to the `:strict` option.
@ -1138,7 +1138,7 @@ end
```irb
irb> Person.new.valid?
TokenGenerationException: Token cant be blank
TokenGenerationException: Token can't be blank
```
Conditional Validation
@ -1395,7 +1395,7 @@ irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors.full_messages
=> ["Name cant be blank", "Name is too short (minimum is 3 characters)"]
=> ["Name can't be blank", "Name is too short (minimum is 3 characters)"]
irb> person = Person.new(name: "John Doe")
irb> person.valid?
@ -1442,7 +1442,7 @@ irb> person = Person.new
irb> person.valid?
=> false
irb> person.errors[:name]
=> ["cant be blank", "is too short (minimum is 3 characters)"]
=> ["can't be blank", "is too short (minimum is 3 characters)"]
```
### `errors.where` and Error Object

View File

@ -972,13 +972,13 @@ irb> person = Person.new.tap(&:valid?)
irb> person.errors.full_messages
=> [
"Invalid Name (cant be blank)",
"Invalid Name (can't be blank)",
"Please fill in your Age"
]
irb> person.errors.messages
=> {
:name => ["cant be blank"],
:name => ["can't be blank"],
:age => ["Please fill in your Age"]
}
```