更新使用活动存储的用户记录不起作用
Updating a user record that uses active-storage doesn't work
我正在练习 Rails active_storage
的用法。所以我创建了一个只有一个模型的应用程序 - User
。 User
有两个主要的数据库列 - username
和 profile_pic
。然后通过active_storage
它has_many_attached :avatars
。我正在实施的功能是 before_validation 的用户记录,我想分配第一个附加头像(用户可以在注册时上传许多图像)作为 profile_pic
。这是完整的模型
class User < ApplicationRecord
include Rails.application.routes.url_helpers
has_many_attached :avatars
validates :username, presence: true
before_validation :assign_profile_pic
def change_profile_pic
self.profile_pic = rails_blob_path(avatars.last, only_path: true)
save
end
private
def assign_profile_pic
self.profile_pic = rails_blob_path(avatars.first, only_path: true)
end
end
这是用户控制器
class V1::UsersController < ApplicationController
# include Rails.application.routes.url_helpers
def show
user = User.find_by(username: params[:username])
if user.present?
render json: success_json(user), status: :ok
else
head :not_found
end
end
def create
user = User.new(user_params)
if user.save
render json: success_json(user), status: :created
else
render json: error_json(user), status: :unprocessable_entity
end
end
def update
user = User.find_by(username: params[:username])
if user.update(user_params)
user.change_profile_pic
render json: success_json(user), status: :accepted
else
render json: error_json(user), status: :unprocessable_entity
end
end
def avatar
user = User.find_by(username: params[:user_username])
if user&.avatars&.attached?
redirect_to rails_blob_url(user.avatars[params[:id].to_i])
else
head :not_found
end
end
private
def user_params
params.require(:user).permit(:username, avatars: [])
end
def success_json(user)
{
user: {
id: user.id,
username: user.username
}
}
end
def error_json(user)
{ errors: user.errors.full_messages }
end
end
创建用户不是问题。它按预期工作,它在创建时自动将 user.avatars.first
分配为 user.profile_pic
。问题发生在 update
部分。你看我在成功更新后调用 change_profile_pic
用户方法(在 users_controller
中)。问题是 user.profile_pic
永远不会更新。我已经调试了很多次, user_params
没有任何问题。我错过了什么?
before_validation
每次在 before_save
之前运行。你设置一次,然后再设置一次。请参阅此处的顺序:https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
如果您只是更改个人资料图片,请避免使用 assign_profile_pic
进行验证。一个干净的方法是使用 ActiveModel::AttributeMethods
class User < ApplicationRecord
include Rails.application.routes.url_helpers
has_many_attached :avatars
validates :username, presence: true
before_validation :assign_profile_pic, unless: :changing_profile_pic?
attribute :changing_profile_pic, :boolean, default: false
def change_profile_pic
self.profile_pic = rails_blob_path(avatars.last, only_path: true)
self.changing_profile_pic = true
save
end
private
def assign_profile_pic
self.profile_pic = rails_blob_path(avatars.first, only_path: true)
end
end
我正在练习 Rails active_storage
的用法。所以我创建了一个只有一个模型的应用程序 - User
。 User
有两个主要的数据库列 - username
和 profile_pic
。然后通过active_storage
它has_many_attached :avatars
。我正在实施的功能是 before_validation 的用户记录,我想分配第一个附加头像(用户可以在注册时上传许多图像)作为 profile_pic
。这是完整的模型
class User < ApplicationRecord
include Rails.application.routes.url_helpers
has_many_attached :avatars
validates :username, presence: true
before_validation :assign_profile_pic
def change_profile_pic
self.profile_pic = rails_blob_path(avatars.last, only_path: true)
save
end
private
def assign_profile_pic
self.profile_pic = rails_blob_path(avatars.first, only_path: true)
end
end
这是用户控制器
class V1::UsersController < ApplicationController
# include Rails.application.routes.url_helpers
def show
user = User.find_by(username: params[:username])
if user.present?
render json: success_json(user), status: :ok
else
head :not_found
end
end
def create
user = User.new(user_params)
if user.save
render json: success_json(user), status: :created
else
render json: error_json(user), status: :unprocessable_entity
end
end
def update
user = User.find_by(username: params[:username])
if user.update(user_params)
user.change_profile_pic
render json: success_json(user), status: :accepted
else
render json: error_json(user), status: :unprocessable_entity
end
end
def avatar
user = User.find_by(username: params[:user_username])
if user&.avatars&.attached?
redirect_to rails_blob_url(user.avatars[params[:id].to_i])
else
head :not_found
end
end
private
def user_params
params.require(:user).permit(:username, avatars: [])
end
def success_json(user)
{
user: {
id: user.id,
username: user.username
}
}
end
def error_json(user)
{ errors: user.errors.full_messages }
end
end
创建用户不是问题。它按预期工作,它在创建时自动将 user.avatars.first
分配为 user.profile_pic
。问题发生在 update
部分。你看我在成功更新后调用 change_profile_pic
用户方法(在 users_controller
中)。问题是 user.profile_pic
永远不会更新。我已经调试了很多次, user_params
没有任何问题。我错过了什么?
before_validation
每次在 before_save
之前运行。你设置一次,然后再设置一次。请参阅此处的顺序:https://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
如果您只是更改个人资料图片,请避免使用 assign_profile_pic
进行验证。一个干净的方法是使用 ActiveModel::AttributeMethods
class User < ApplicationRecord
include Rails.application.routes.url_helpers
has_many_attached :avatars
validates :username, presence: true
before_validation :assign_profile_pic, unless: :changing_profile_pic?
attribute :changing_profile_pic, :boolean, default: false
def change_profile_pic
self.profile_pic = rails_blob_path(avatars.last, only_path: true)
self.changing_profile_pic = true
save
end
private
def assign_profile_pic
self.profile_pic = rails_blob_path(avatars.first, only_path: true)
end
end