0

I have a form to create a new contact for an address book. In the model, the first_name and last_name fields are required:

models/contact.rb

class Contact < ApplicationRecord
  [...]
  validates :first_name, :last_name, presence: true
end

I have code which should show the messages if there are errors in the creation of the new contact:

views/contacts/_form.html.erb

<%= form_with model: @contact do |form| %>

  <% if @contact.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@contact.errors.count, "error") %> prevented this contact from being saved:
      </h2>
      <ul>
        <% @contact.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= form.label :salutation %><br>
    <%= form.select :salutation, options_for_select([['Mr.'], ['Mrs.'], ['Ms.'], ['Mx']]), class: "form-control"  %><br>
    <%= form.label :first_name, "First Name*" %><br>
    <%= form.text_field :first_name, class: "form-control" %><br>
    <%= form.label :middle_name, "Middle Name" %><br>
    <%= form.text_field :middle_name, class: "form-control" %><br>
    <%= form.label :last_name, "Last Name*" %><br>
    <%= form.text_field :last_name, class: "form-control" %>
    [...]

When I enter a contact with the first or last name missing, the contact is not created and the page stays on the form. However, no errors appear at the top of the view. I added some debugging in my controller and discovered that although the submission is invalid, there are no errors created:

controllers/contacts_controller.rb

[...]
 def create
    @contact = Contact.new(contact_params)
    logger.debug "New contact: #{@contact.attributes.inspect}"
    logger.debug "Contact should have errors: #{@contact.errors.any?}"
    logger.debug "Contact should be invalid: #{@contact.invalid?}"
[...]

This produces the following response in the terminal:

Started POST "/contacts" for ::1 at 2020-09-28 11:42:47 +0200
Processing by ContactsController#create as JS
  Parameters: {"authenticity_token"=>"2GBdtJXn77B9+IQuXg03C9HFgMS+ayzqP5lke49HcsvcM02L6lgyoGXuOtKL72mBzNsFU6EawC2dU+mN6RZzkA==", "contact"=>{"salutation"=>"Mrs.", "first_name"=>"Sue", "middle_name"=>"", "last_name"=>"", "ssn"=>"", "dob"=>"", "comment"=>""}, "commit"=>"Create Contact"}
New contact: {"id"=>nil, "salutation"=>"Mrs.", "first_name"=>"Sue", "middle_name"=>"", "last_name"=>"", "ssn"=>"", "dob"=>"", "comment"=>"", "created_at"=>nil, "updated_at"=>nil}
Contact should have errors: false
Contact should be invalid: true
  Rendering contacts/new.html.erb within layouts/application
  Rendered contacts/_form.html.erb (Duration: 4.7ms | Allocations: 1484)
  Rendered contacts/new.html.erb within layouts/application (Duration: 5.0ms | Allocations: 1569)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 70ms (Views: 20.1ms | ActiveRecord: 27.1ms | Allocations: 18926)

This is strange to me: Contact should have errors: false; Contact should be invalid: true As far as I know, my validation in my model is correct, and the submission is being recognized as invalid, but this doesn't translate to errors for some reason. What do I need to change?

Any help would be really great! Thank you for looking.

EDIT:

Here is the full create method, with the .save method included:

def create
    @contact = Contact.new(contact_params)

    if @contact.save
      redirect_to @contact, notice: 'Contact was successfully created'
    else
      render 'new'
    end
  end

Here is the image of the webpage after attempting to submit an invalid request:

network tab view with errors displayed

1
  • It should be noted that there is a big difference between validation "errors" and actual exceptions. A failed validation does not raise an exception, it just adds an entry in the errors object which prevents the object from being saved. It only when you use the "bang methods" .save! and .create! that Rails will raise an RecordNotValid exception if the record is not valid. Commented Sep 28, 2020 at 11:29

1 Answer 1

1

Contact.new initializes a new Contact object, but does not validate or store it.

Call valid? or invalid? to validate it. This will add the errors to the record. If you call save (or save!) on it, it will also run the validations before storing the record.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your response, @Siim ! I should have included the full show method in my original post, but it does include a call to ".save" [see the update above]. I see that if I move the debugging to the else clause, the errors are now attached. That means the problem might be with the @contact.errors.any? code block in the form, but I don't see what the issue might be. When I view the network tab, it shows a view with the errors attached. You can see an image of this above as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.