Ruby on Rails Active Record return value when create fails?

后端 未结 2 868
情书的邮戳
情书的邮戳 2021-02-13 00:02

I am new to ruby on rails and having trouble getting this work. Basically I have a user registration page which has a password confirmation. In the User class I have the followi

2条回答
  •  礼貌的吻别
    2021-02-13 00:43

    The answer to your question is, User.create returns a User instance if it succeeds or fails. If it fails because of validations, the instance will be invalid and will have errors:

    user.valid? # <= returns false
    user.errors.count # <= will be > 0
    user.errors.blank? # <= will be false
    

    So your code would change from this:

    if user==false or user==nil or user==vals
    

    to this:

    if !user.valid?
    

    You can also use this pattern:

    user.attributes = vals
    if user.save
       ... save succeeded ...
    else
       ... save failed ...
    end
    

    The save method returns a boolean true or false since you are calling it on an existing instance.

    But lets get you on the right track in a few other ways:

    First: you have this:

    if User.exists(vals[:username])
    

    (I'm assuming exits is a method you put on your User model because that's not a Rails thing). Instead of doing that check in your controller, you can just use another validation on the model:

    class User < ActiveRecord::Base
       ...
       validates :username, unique: true
       ...
    end
    

    Now when you try to create the user, it will fail validation if you already have one with that name.

    Second: You have this:

    vals[:create_date] = DateTime.current
    

    This is unnecessary. If you add a column to your model called created_at it will hold the creation date automatically (managed by ActiveRecord). You can add this, and its partner updated_at to your model in your migration like this:

    create_table :users do |t|
       ...
       t.timestamps # <= tells rails to add created_at and updated_at
    end
    

    Or, since you already have a users table:

    add_column :users, :created_at, :datetime
    add_column :users, :updated_at, :datetime
    

    Now you will always have the date/time of creation and last update on your user model with no need for additional code.

    Third: You have this:

    user = User.create(vals, :without_protection => :true)
    

    Don't do this. Instead, change this:

    vals = params[:user]
    

    To this:

    vals = params.require(:user).permit(:username, :password, :password_confirmation)
    

    And then keep protection on:

    user = User.create(vals)
    

    You can add any additional columns you want to bring from your form to the permit() call. This is very important because it is hard to fix this kind of thing later. "If once you go down the dark path, forever will it dominate your destiny."

    Fourth: You should not redirect to the user_path if the save failed, because there will be no user model to show. Instead you should re-render your new form. You also don't need flash messages for the errors. If the new form renders, it can check @user.errors and report error messages accordingly. See the ActiveRecord error object documentation.

    Finally: You mention that you your validation fails even when your password is properly confirmed. I can't say for sure without seeing your form code, but make sure your password field is called password and the confirmation field is called password_confirmation. Rails looks for this *_confirmation field value specifically when validating for confirmation.

    If that doesn't do it, post your form code and I'll revise.

提交回复
热议问题