carrierwave 不保存文件也不更新模型
carrierwave doesn't save file neither update model
嗨,我在 rails api 中使用载波来上传用户头像...在我的控制器中,我有一个方法 update_avatar 可以更新 user.avatar_uri给定的文件。
我查阅了 carrierwave 的文档并按照每个步骤进行操作,但它不起作用。它既不保存文件也不保存模型本身..
这是控制器users_controller.rb
def update_avatar
parameters = Hash.new
user = User.find_by(id: params[:user_id])
if user
#p("----user.avatar_uri.url before user.avatar_uri = params[:avatar] : "+user.avatar_uri.url)
user.is_used_fb_avatar=false
p("----user.avatar_uri.url before update: "+ user.avatar_uri.url)
User.update(params[:user_id], :avatar_uri => params[:avatar])
p("----user.avatar_uri.url after update: "+user.avatar_uri.url)
if user.avatar_uri
parameters["success"]=true
parameters["avatar_uri"]=user.avatar_uri.url
else
parameters["success"]=false
parameters["error"]="Couldn't update user check the file used"
end
else
parameters["success"]=false
parameters["error"]="Couldn't find user"
end
render :json => parameters.to_json
end
这是模型user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
mount_uploader :avatar_uri, AvatarUploader
attr_accessor :login
has_one :role, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :shares, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :messages
has_many :notifications, dependent: :destroy
has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy
has_many :tokens
has_and_belongs_to_many :conversations
...
end
这是上传者avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
def store_dir
"#{model.class.to_s.underscore}/image"
end
def extension_whitelist
%w(jpg jpeg gif png)
end
def cache_dir
"tmp/"
end
def filename
if model.is_used_fb_avatar
original_filename
#puts ("--------- is_used_fb_avatar is called ----")
else
SecureRandom.urlsafe_base64(16).to_s+ File.extname(original_filename).to_s if original_filename
puts ("--------- is_used_fb_avatar is not called ----")
puts ("filename => "+ SecureRandom.urlsafe_base64(16).to_s+File.extname(original_filename).to_s)
end
end
end
这是我从服务器获得的控制台日志:
Started PUT "/api/update-user-avatar.json" for 127.0.0.1 at 2017-06-30 21:10:43 +0200
Processing by Api::UsersController#update_avatar as JSON
Parameters: {"user_id"=>"47", "avatar"=>#<ActionDispatch::Http::UploadedFile:0x007f852d2c54e8 @tempfile=#<Tempfile:/var/folders/k7/2bnc1fxs1r164gf831dn5l140000gn/T/RackMultipart20170630-1261-1viplk8.jpg>, @original_filename="batman.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"avatar\"; filename=\"batman.jpg\"\r\nContent-Type: image/jpeg\r\n">}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 47], ["LIMIT", 1]]
"----user.avatar_uri.url before update: /user/image/wlOHg5N0K5aq5hJGFlM6XA.png"
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 47], ["LIMIT", 1]]
(0.3ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = AND ("users"."id" != ) LIMIT [["username", "John"], ["id", 47], ["LIMIT", 1]]
--------- is_used_fb_avatar is not called ----
filename => jDZ48CtHI5a9L0qGcKdEWQ.jpg
SQL (37.7ms) UPDATE "users" SET "updated_at" = , "avatar_uri" = WHERE "users"."id" = [["updated_at", 2017-06-30 19:10:45 UTC], ["avatar_uri", "wlOHg5N0K5aq5hJGFlM6XA.png"], ["id", 47]]
--------- is_used_fb_avatar is not called ----
filename => njeFYobP6erVu9uYunmFhw.jpg
(134.3ms) COMMIT
"----user.avatar_uri.url after update: /user/image/wlOHg5N0K5aq5hJGFlM6XA.png"
Completed 200 OK in 683ms (Views: 136.7ms | ActiveRecord: 222.4ms)
你可以看到上传器中的 def filename 在没有保存模型的情况下被调用了两次,也没有保存文件...
"wlOHg5N0K5aq5hJGFlM6XA.png" 是 avatar_uri 列的旧值,它不会被 "njeFYobP6erVu9uYunmFhw.jpg" 新值替换..
==>[回答]:
感谢@Micael Nussbaumer 解决了它...问题是直接在我的上传器中使用 SecureRandom 所以我将其更改为:
def filename
if model.is_used_fb_avatar
original_filename
#puts ("--------- is_used_fb_avatar is called ----")
else
"avatar-#{secure_token}.jpg" if original_filename.present?
end
end
protected
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
试试这个:
def filename
"avatar-#{secure_token}.jpg" if original_filename.present?
end
protected
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
嗨,我在 rails api 中使用载波来上传用户头像...在我的控制器中,我有一个方法 update_avatar 可以更新 user.avatar_uri给定的文件。
我查阅了 carrierwave 的文档并按照每个步骤进行操作,但它不起作用。它既不保存文件也不保存模型本身..
这是控制器users_controller.rb
def update_avatar
parameters = Hash.new
user = User.find_by(id: params[:user_id])
if user
#p("----user.avatar_uri.url before user.avatar_uri = params[:avatar] : "+user.avatar_uri.url)
user.is_used_fb_avatar=false
p("----user.avatar_uri.url before update: "+ user.avatar_uri.url)
User.update(params[:user_id], :avatar_uri => params[:avatar])
p("----user.avatar_uri.url after update: "+user.avatar_uri.url)
if user.avatar_uri
parameters["success"]=true
parameters["avatar_uri"]=user.avatar_uri.url
else
parameters["success"]=false
parameters["error"]="Couldn't update user check the file used"
end
else
parameters["success"]=false
parameters["error"]="Couldn't find user"
end
render :json => parameters.to_json
end
这是模型user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
mount_uploader :avatar_uri, AvatarUploader
attr_accessor :login
has_one :role, dependent: :destroy
has_many :posts, dependent: :destroy
has_many :likes, dependent: :destroy
has_many :shares, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :messages
has_many :notifications, dependent: :destroy
has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy
has_many :tokens
has_and_belongs_to_many :conversations
...
end
这是上传者avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
def store_dir
"#{model.class.to_s.underscore}/image"
end
def extension_whitelist
%w(jpg jpeg gif png)
end
def cache_dir
"tmp/"
end
def filename
if model.is_used_fb_avatar
original_filename
#puts ("--------- is_used_fb_avatar is called ----")
else
SecureRandom.urlsafe_base64(16).to_s+ File.extname(original_filename).to_s if original_filename
puts ("--------- is_used_fb_avatar is not called ----")
puts ("filename => "+ SecureRandom.urlsafe_base64(16).to_s+File.extname(original_filename).to_s)
end
end
end
这是我从服务器获得的控制台日志:
Started PUT "/api/update-user-avatar.json" for 127.0.0.1 at 2017-06-30 21:10:43 +0200
Processing by Api::UsersController#update_avatar as JSON
Parameters: {"user_id"=>"47", "avatar"=>#<ActionDispatch::Http::UploadedFile:0x007f852d2c54e8 @tempfile=#<Tempfile:/var/folders/k7/2bnc1fxs1r164gf831dn5l140000gn/T/RackMultipart20170630-1261-1viplk8.jpg>, @original_filename="batman.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"avatar\"; filename=\"batman.jpg\"\r\nContent-Type: image/jpeg\r\n">}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 47], ["LIMIT", 1]]
"----user.avatar_uri.url before update: /user/image/wlOHg5N0K5aq5hJGFlM6XA.png"
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 47], ["LIMIT", 1]]
(0.3ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = AND ("users"."id" != ) LIMIT [["username", "John"], ["id", 47], ["LIMIT", 1]]
--------- is_used_fb_avatar is not called ----
filename => jDZ48CtHI5a9L0qGcKdEWQ.jpg
SQL (37.7ms) UPDATE "users" SET "updated_at" = , "avatar_uri" = WHERE "users"."id" = [["updated_at", 2017-06-30 19:10:45 UTC], ["avatar_uri", "wlOHg5N0K5aq5hJGFlM6XA.png"], ["id", 47]]
--------- is_used_fb_avatar is not called ----
filename => njeFYobP6erVu9uYunmFhw.jpg
(134.3ms) COMMIT
"----user.avatar_uri.url after update: /user/image/wlOHg5N0K5aq5hJGFlM6XA.png"
Completed 200 OK in 683ms (Views: 136.7ms | ActiveRecord: 222.4ms)
你可以看到上传器中的 def filename 在没有保存模型的情况下被调用了两次,也没有保存文件...
"wlOHg5N0K5aq5hJGFlM6XA.png" 是 avatar_uri 列的旧值,它不会被 "njeFYobP6erVu9uYunmFhw.jpg" 新值替换..
==>[回答]: 感谢@Micael Nussbaumer 解决了它...问题是直接在我的上传器中使用 SecureRandom 所以我将其更改为:
def filename
if model.is_used_fb_avatar
original_filename
#puts ("--------- is_used_fb_avatar is called ----")
else
"avatar-#{secure_token}.jpg" if original_filename.present?
end
end
protected
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
试试这个:
def filename
"avatar-#{secure_token}.jpg" if original_filename.present?
end
protected
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end