Why does my rails rollback when I try to user.save?
Your user model probably has validations which are not satisfied. Since you've not posted those I'm unable to really solve your question. To make live easier you can debug why your user isn't willing to save.
Try running
user.errors.full_messages
which should give you a hint what's going wrong.
Rails rollback while saving model
License model contains two foreign key user_id
and license_type_id
=> Which means before create License
there must be a user who own this License
as Rails 5 convention says user_id
must exist
=> Also there must exist LicenseType
as Rails 5 convention says license_type_id
must exist
The rollback reasons can be investigated by following
license = License.new(license_types_id: LicenseType.first.id)
license.save
#Begin
#ROLLBACK
errors_stack = license.errors
errors_stack
contains model level errors which causes rollback
To fix these rollback issue
user = User.first #or current_user
license = user.license.new(license_type_id: LicenseType.first.id)
license.save
Or
user = User.first #or current_user
license = License.new(license_type_id: LicenseType.first.id, user_id: user.id)
license.save
Or To create a User
and assign the user a License
# Alternative of after_create :create_assocs
new_user = User.new(...)
new_user.license.build(license_type_id: LicenseType.first.id)
new_user.save
Rollback happens when I update user model in Rails?
The SELECT 1 ...
query inside the transaction looks like the query checking for uniqueness. And in fact, your model has a uniqueness validation. When there is no data inserted after this query then there is a high chance that this validation failed and therefore Rails rolls back all things done in the concept of this save
operation.
That means you tried to create a user with a username that already exists in the database.
To see exactly what when wrong and to give the user feedback I suggest returning validation errors to the user. This could be done by changing your controller method to:
def update
user = User.find_by(id: params[:id])
if user.update(user_params)
render json: user, status: :ok
else
render json: user.errors, status: :unprocessable_entity
end
end
why rails rollback unexpected when i try to create a new user in the database?
In the create action, replace:
User.new(params[:id])
with:
User.new params.require(:user).permit(:name, :email, :password, :password_confirmation)
To get data passed to the active record model.
As for why it failed:
- I guess you have a unicity validation on email
- you pass no email (because wrong params)
- you may already have an empty email in database
- validation fails
Fun fact: it's a good example to have database ensure you have expected data (are null emails really allowed?)
rails console rollback on save
The thing is, the record doesn't contain a field called password, it has password_hash
and password_salt
, any time you try to save rails looks for the password field but can't find it, i'd say create a condition that tell rails when to look for a password, for example
validates :password, if: :password_required?
def password_required?
user.changes.include? :email # just an example
end
This will prevent asking for passowrd every time the user changes something minor in his account, and it will ask for the password if the user changes his email, you could add more options of course.
If you want to force the saving of the user in the time being, you could tell rails to skip validations
user.save(validate: false)
Also as a last note, it's better and safer to use a well developed and mature authentication gem like devise, it has all the features you'd need in any authentication.
Why does Rails rollback even though the model exists?
I think your validations are the issue. Password presence is validating on every update. Since User#password
is nil
and you don't have a password in your params, it fails.
class User < ApplicationRecord
has_secure_password
validates :password, presence: true, confirmation: true
end
>> User.create(email: 'test@user.com', password: '123456');
>> User.first.update!(email: 'test@user.com')
User Load (0.8ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
ActiveRecord::RecordInvalid: Validation failed: Password can't be blank
has_secure_password
also adds its own validations.
https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password
If you want to customize password validations use
has_secure_password validations: false
# + your password validations
To get some ideas, you can take a look at how devise
does validations:
https://github.com/heartcombo/devise/blob/v4.8.1/lib/devise/models/validatable.rb#L60
Related Topics
Storing Arrays in Database Using Activerecord
How Does Ruby's Sort_By {Rand} Work
How to Robustly Parse Malformed CSV
How to Write Rake Task to Import Data to Rails App
How to Remove a Node with Nokogiri
Doing a Http Basic Authentication in Rails
Rails - Pass Id Parameter on a Link_To
Failing Installing Pg Gem, "Mkmf.Rb Can't Find Header Files for Ruby" (MAC Osx 10.6.5)
Check If Internet Connection Exists with Ruby
Loaderror Running Mongrel with Rails3 and Ruby 1.9.2
How to Dump Strings in Yaml Using Literal Scalar Style
How to Track the Execution Process of Ruby Program
Decrypting Salted Aes File Generated on Command Line with Ruby
Throw Exception When Re-Assigning a Constant in Ruby