Contact form: error on seeding and error messages

2019-09-10 07:47发布

问题:

The app I'm building includes a contact form. On seeding it generates an error message that I don't understand:

ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR:  null value in column "name" violates not-null constraint
DETAIL:  Failing row contains (1, null, null, null, 2015-06-06 13:43:12.339477, 2015-06-06 13:43:12.339477).
: INSERT INTO "messages" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"

Below is the relevant code for the form. If I remove the line attr_accessor :name, :email, :content from the model file it succesfully seeds (I have no idea why this makes a difference for seeding). But even then on the development server, if I go to the contact form and submit without any values, the error messages don't seem to function properly. No matter the error it just gives a single error message "An error occurred while delivering this message", while for all other forms, the error message specifies the variable(s) and type of error. What could be causing this behavior?

The model file for the contact form:

class Message < ActiveRecord::Base
  attr_accessor :name, :email, :content
  validates :name,      presence: true,
                        length: { maximum: 255 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email,     presence: true,
                        length: { maximum: 255 },
                        format: { with: VALID_EMAIL_REGEX }
  validates :content,   presence: true,
                        length: { maximum: 600 }
end

The migration file includes:

  t.string :name,       null: false,    limit: 255
  t.string :email,      null: false,    limit: 255
  t.string :content,    null: false,    limit: 600

In my seeds file I have:

Message.create!(email: "example@example.com",
                name:  "Example User",
                content: "This is my message")

Update: Regarding the error message, I have the following controller method:

  def create
    @message = Message.new(message_params)
    if @message.valid?
      MessageMailer.new_message(@message).deliver_now
      flash[:success] = "Your messages has been sent."
      redirect_to contact_path
    else
      flash[:alert] = "An error occurred while delivering this message."
      render 'new'
    end
  end

I removed the flash alert line. Other forms that I have that do function properly, don't have this line either and I though this flash message might be overwriting the other, more specific error messages. After removing this line and submitting invalid information, the form just makes the invalid fields red but shows no error messages at all. In other forms I would for example get these kinds of error messages:

 The form contains 5 errors.
    Email can't be blank
    Email is invalid
    Username can't be blank
    Username is too short (minimum is 6 characters)
    Username is invalid

The log file is:

Started GET "/contact" for xx.xxx.xx.xxx at 2015-06-06 14:15:43 +0000
  ActiveRecord::SchemaMigration Load (0.5ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by MessagesController#new as HTML
  Rendered messages/new.html.erb within layouts/application (493.2ms)
  Rendered layouts/_shim.html.erb (0.4ms)
  Rendered layouts/_header.html.erb (10.5ms)
  Rendered layouts/_footer.html.erb (0.8ms)
Completed 200 OK in 1454ms (Views: 1429.3ms | ActiveRecord: 3.1ms)

Started POST "/contact" for xx.xxx.xx.xxx at 2015-06-06 14:15:49 +0000
Processing by MessagesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"zAxxxSKMYKey/jxmqqvxxxr***43g2Ud9r6SQ==", "message"=>{"name"=>"", "email"=>"", "content"=>""}, "commit"=>"Send"}
  Rendered messages/new.html.erb within layouts/application (7.3ms)
  Rendered layouts/_shim.html.erb (0.1ms)
  Rendered layouts/_header.html.erb (3.2ms)
  Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 849ms (Views: 844.9ms | ActiveRecord: 0.0ms)

回答1:

Adding attr_accessor :name is equivalent to the following code

def name
  @name
end

def name=(val)
  @name = val
end

So if you have a column named name in your database, it will not be written. That is what happens here. Since you set those columns to be null: false, postgres raises an error if they are null.