为什么 Rails 回滚即使模型存在?
Why does Rails rollback even though the model exists?
我想找出为什么我的更新方法在 Rails API 中不起作用。它应该更新生物领域。我将 API 托管在 Heroku 上,并使用 Heroku 日志在生产环境中进行调试。我用了exists?方法来确保用户在数据库中,但是当调用更新方法时,它会在执行此检查后回滚。我不明白这是什么原因?
这是输出的 Heroku 日志
2022-04-15T02:54:34.083586+00:00 app[web.1]: I, [2022-04-15T02:54:34.083515 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Started PATCH "/users/8" for 98.248.0.125 at 2022-04-15 02:54:34 +0000
2022-04-15T02:54:34.084345+00:00 app[web.1]: I, [2022-04-15T02:54:34.084290 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Processing by UsersController#update as HTML
2022-04-15T02:54:34.084376+00:00 app[web.1]: I, [2022-04-15T02:54:34.084350 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Parameters: {"bio"=>"test", "id"=>"8", "user"=>{"bio"=>"test"}}
2022-04-15T02:54:34.087450+00:00 app[web.1]: D, [2022-04-15T02:54:34.087403 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.089711+00:00 app[web.1]: D, [2022-04-15T02:54:34.089664 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.2ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = LIMIT [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.092004+00:00 app[web.1]: D, [2022-04-15T02:54:34.091963 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) BEGIN
2022-04-15T02:54:34.093523+00:00 app[web.1]: D, [2022-04-15T02:54:34.093465 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.4ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = AND "users"."id" != LIMIT [["username", "newperson"], ["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.095530+00:00 app[web.1]: D, [2022-04-15T02:54:34.095493 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) ROLLBACK
2022-04-15T02:54:34.096881+00:00 app[web.1]: I, [2022-04-15T02:54:34.096842 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.07ms)
2022-04-15T02:54:34.097078+00:00 app[web.1]: I, [2022-04-15T02:54:34.097050 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Completed 422 Unprocessable Entity in 13ms (Views: 0.6ms | ActiveRecord: 5.5ms | Allocations: 2816)
2022-04-15T02:54:34.101664+00:00 heroku[router]: at=info method=PATCH path="/users/8" host=anime-axis-api.herokuapp.com request_id=9e5ea776-5b15-420f-8cdc-0601480e0e3d fwd="98.248.0.125" dyno=web.1 connect=0ms service=17ms status=422 bytes=1096 protocol=https
这是我的更新方法:
def update
if User.exists?(8)
@current_user.update!(user_params)
render json: @current_user, status: :ok
end
end
private
def user_params
# added require
params.require(:user).permit(:username, :password, :password_confirmation, :bio, :avatar, :email)
end
我的用户模型:
class User < ApplicationRecord
has_secure_password
has_many :anime_lists
has_many :animes, through: :anime_lists
has_many :manga_lists
has_many :mangas, through: :manga_lists
validates :username, presence: true, confirmation: {case_sensitive: false}, uniqueness: true, length: {in: 6..30}
validates :password, presence: true, confirmation: true
end
如果不知道你数据库中的数据,我不能完全确定,但我会说你有两个用户 username=newperson
。
当您尝试保存对任何验证触发器的任何更改时,更改不会提交到数据库。
我认为您的验证是问题所在。每次更新都会验证密码是否存在。由于 User#password
是 nil
并且您的参数中没有密码,因此失败。
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 [["LIMIT", 1]]
ActiveRecord::RecordInvalid: Validation failed: Password can't be blank
has_secure_password
还添加了自己的验证。
如果您想自定义密码验证,请使用
has_secure_password validations: false
# + your password validations
要获得一些想法,您可以看看 devise
如何进行验证:
https://github.com/heartcombo/devise/blob/v4.8.1/lib/devise/models/validatable.rb#L60
我想找出为什么我的更新方法在 Rails API 中不起作用。它应该更新生物领域。我将 API 托管在 Heroku 上,并使用 Heroku 日志在生产环境中进行调试。我用了exists?方法来确保用户在数据库中,但是当调用更新方法时,它会在执行此检查后回滚。我不明白这是什么原因?
这是输出的 Heroku 日志
2022-04-15T02:54:34.083586+00:00 app[web.1]: I, [2022-04-15T02:54:34.083515 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Started PATCH "/users/8" for 98.248.0.125 at 2022-04-15 02:54:34 +0000
2022-04-15T02:54:34.084345+00:00 app[web.1]: I, [2022-04-15T02:54:34.084290 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Processing by UsersController#update as HTML
2022-04-15T02:54:34.084376+00:00 app[web.1]: I, [2022-04-15T02:54:34.084350 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Parameters: {"bio"=>"test", "id"=>"8", "user"=>{"bio"=>"test"}}
2022-04-15T02:54:34.087450+00:00 app[web.1]: D, [2022-04-15T02:54:34.087403 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Load (1.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.089711+00:00 app[web.1]: D, [2022-04-15T02:54:34.089664 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.2ms) SELECT 1 AS one FROM "users" WHERE "users"."id" = LIMIT [["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.092004+00:00 app[web.1]: D, [2022-04-15T02:54:34.091963 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) BEGIN
2022-04-15T02:54:34.093523+00:00 app[web.1]: D, [2022-04-15T02:54:34.093465 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] User Exists? (1.4ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = AND "users"."id" != LIMIT [["username", "newperson"], ["id", 8], ["LIMIT", 1]]
2022-04-15T02:54:34.095530+00:00 app[web.1]: D, [2022-04-15T02:54:34.095493 #4] DEBUG -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] TRANSACTION (0.9ms) ROLLBACK
2022-04-15T02:54:34.096881+00:00 app[web.1]: I, [2022-04-15T02:54:34.096842 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.07ms)
2022-04-15T02:54:34.097078+00:00 app[web.1]: I, [2022-04-15T02:54:34.097050 #4] INFO -- : [9e5ea776-5b15-420f-8cdc-0601480e0e3d] Completed 422 Unprocessable Entity in 13ms (Views: 0.6ms | ActiveRecord: 5.5ms | Allocations: 2816)
2022-04-15T02:54:34.101664+00:00 heroku[router]: at=info method=PATCH path="/users/8" host=anime-axis-api.herokuapp.com request_id=9e5ea776-5b15-420f-8cdc-0601480e0e3d fwd="98.248.0.125" dyno=web.1 connect=0ms service=17ms status=422 bytes=1096 protocol=https
这是我的更新方法:
def update
if User.exists?(8)
@current_user.update!(user_params)
render json: @current_user, status: :ok
end
end
private
def user_params
# added require
params.require(:user).permit(:username, :password, :password_confirmation, :bio, :avatar, :email)
end
我的用户模型:
class User < ApplicationRecord
has_secure_password
has_many :anime_lists
has_many :animes, through: :anime_lists
has_many :manga_lists
has_many :mangas, through: :manga_lists
validates :username, presence: true, confirmation: {case_sensitive: false}, uniqueness: true, length: {in: 6..30}
validates :password, presence: true, confirmation: true
end
如果不知道你数据库中的数据,我不能完全确定,但我会说你有两个用户 username=newperson
。
当您尝试保存对任何验证触发器的任何更改时,更改不会提交到数据库。
我认为您的验证是问题所在。每次更新都会验证密码是否存在。由于 User#password
是 nil
并且您的参数中没有密码,因此失败。
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 [["LIMIT", 1]]
ActiveRecord::RecordInvalid: Validation failed: Password can't be blank
has_secure_password
还添加了自己的验证。
如果您想自定义密码验证,请使用
has_secure_password validations: false
# + your password validations
要获得一些想法,您可以看看 devise
如何进行验证:
https://github.com/heartcombo/devise/blob/v4.8.1/lib/devise/models/validatable.rb#L60