Does Ruby on Rails Active Record return a value when a crash occurs?

I am new to rubies on rails and can't get this job. Basically, I have a user registration page with a password confirmation. In the User class, I have the following check:

validates :password, confirmation: true 

And in the controller I have

 def create vals = params[:user] if(User.exists(vals[:username])) flash[:warning] = "#{vals[:username]} already exists! Please try a new one. " else vals[:create_date] = DateTime.current user = User.create(vals, :without_protection => :true) if user==false or user==nil or user==vals flash[:warning] = "#{vals[:username]} has not been registered successfully. " else flash[:notice] = "#{vals[:username]} has been registered. " end end redirect_to users_path end 

The problem is that when the password matches the confirmation, I still get a notification indicating that the registration was successful. As you can see, I tried several return values ​​for create , but none of them seem successful. I am sure that the verification works because I do not see the user I just created if the password does not match the confirmation. Also, when I use create! , I see that the website crashes with a validation error. Can someone help me tell me that create should return if the record is not confirmed?

Thanks.

+7
ruby ruby-on-rails activerecord rails-activerecord
source share
2 answers

The answer to your question: User.create returns a User instance if it succeeds or fails. If this fails due to validation, 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 will change:

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

:

 if !user.valid? 

You can also use this template:

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

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

But let's meet you on the right track in several ways:

First: you have this:

 if User.exists(vals[:username]) 

(I assume that exits is a method that you put in your User model because it is not a Rails thing). Instead of doing this check in your controller, you can simply use a different check on the model:

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

Now, when you try to create a user, he will not be able to check if you already have a name with that name.

Second: You have the following:

 vals[:create_date] = DateTime.current 

It is not necessary. If you add a column to your model called created_at , it will automatically save the creation date (managed by ActiveRecord). You can add this and its updated_at partner to your model in your migration as follows:

 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 creation date / time and the last update of your user model without the need to add additional code.

Third: You have the following:

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

Do not do this. Instead, change this:

 vals = params[:user] 

For this:

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

And then save the protection:

 user = User.create(vals) 

You can add any additional columns that you want to bring from the form to the permit() call. This is very important because it is difficult to resolve later. "If one day you go down the dark path, it will forever dominate your destiny."

Fourth: You cannot redirect the user_path if the failure failed because the user model will not be displayed. Instead, you should redisplay your new form. You also don't need flash error messages. If the new form displays, it can check @user.errors and report errors. See Documentation ActiveRecord Error Documentation .

Finally: You mentioned that your verification failed, even when your password was correctly verified. 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 password_confirmation . Rails searches for this value of the *_confirmation field specifically when checking for confirmation.

If this is not the case, submit your form code and I will change my mind.

+21
source share

Answer: ActiveRecord object . The official source code shows that create returns an object if it succeeds or fails:

 # File activerecord/lib/active_record/persistence.rb, line 29 def create(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create(attr, &block) } else object = new(attributes, &block) object.save object end end 

How to judge it successfully or fails

persisted? real answer persisted? :

 if user.persisted? # Success else # Failed end 

Why not use user.valid? for this? Because sometimes this is not enough when there are some callbacks that control other models:

 class One < ActiveRecord::Base has_many :twos after_create :create_twos_after_create def create_twos_after_create # Use bang method in callbacks, than it will rollback while create two failed twos.create!({}) # This will fail because lack of the column `number` end end class Two < ActiveRecord::Base validates :number, presence: true end 

Now, we will execute One.create , it will not work, check the log file, it will be rolled back, because it could not create two. In this case, One.create.valid? still returns true , but it actually fails, why use One.create.persisted? to replace it is necessary.

Note. Code tested in Rails 5.1.

0
source share

All Articles