播种失败并出现验证错误

Seeding fails with validation error

我向我的用户模型添加了一个新变量 new_email。为此我补充说:

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :new_email,     length: { maximum: 255 },
                          format: { with: VALID_EMAIL_REGEX }

在迁移文件中:

t.string   :new_email

关于这个新变量,我没有在我的种子文件中添加任何内容。播种时出现错误:ActiveRecord::RecordInvalid: Validation failed: New email is invalid。如果我从模型文件中删除 validates 行,它就会成功播种。我已尝试重置我的数据库:rake db:droprake db:createrake db:migraterake db:seed,但结果相同。什么可能导致此错误?

使用参数的控制器方法:

  def create
    @user = User.new(usernew_params)
    if @user.save                       
      @user.send_activation_email
      flash[:success] = "A confirmation email has been sent to you"
      redirect_to root_url
    else                            
      render 'new'
    end
  end

  def update
    @user = User.friendly.find(params[:id])
    if @user.update_attributes(userupdate_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end

private
    def usernew_params
      params.require(:user).permit(:email,
                                   :username,
                                   :password, 
                                   :password_confirmation)
    end

    def userupdate_params
        params.require(:user).permit(:email,
                                     :email_new,
                                     :avatar,
                                     :organization, 
                                     :activated, 
                                     :password, 
                                     :password_confirmation)
    end

还有我的种子文件(省略了与该模型无关的其他模型):

99.times do |n|
  username  = "fakename#{n+1}"
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  organization = Faker::Company.name
  User.create!(username:               username,
               email:                  email,
               password:               password,
               password_confirmation:  password,
               activated:              true,
               activated_at:           Time.zone.now,
               organization:           organization)
end

问题是您在每个请求上验证 new_email 并且不允许它为空。由于它未在您的种子文件中设置,并且您正在根据 Regexp 进行验证,因此每次都会失败。

根据您描述的用例,我会推荐这个

validates :new_email, length: { maximum: 255 },
                      format: { with: VALID_EMAIL_REGEX },
                      allow_blank: true,
                      on: :update

这将做两件事:

  • 它将允许 new_email 为空白 "" 或完全省略 nil 而不会失败。
  • 此外,由于您在通过控制器创建时甚至不接受 new_email,因此此验证只会在 update 上 运行。

虽然 allow_blank 的验证相当轻量级,但我仍然尝试建议在不需要时不要使用 运行ning 代码,这就是我添加 on 参数的原因。