今回の経緯
Userテーブルのemailの値とimageファイルの変更に失敗する。
次の画像は、実際にUserテーブルを更新した際に上手く動作しなかった時の映像です。
ターミナルは次のような処理が走っています。
Started PATCH "/users/71" for ::1 at 2019-06-15 19:54:55 +0900
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"a2Ma+qZALw6OESo45mSJ1hWQv18YyK5h86pkt6edPFgQzfEyI8w9k5ILpTThxyFIZ4vOOCavP+Kn3C17SgZsgw==", "user"=>{"email"=>"aaa@bbb.ccc", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007fba4aa027e0 @tempfile=#<Tempfile:/var/folders/v1/rm2pdthd0jg_brcdz1d64ht40000gn/T/RackMultipart20190615-10003-1vnlx4b.JPG>, @original_filename="RIMG0005.JPG", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"user[image]\"; filename=\"RIMG0005.JPG\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"確定", "id"=>"71"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 71], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:53
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 71], ["LIMIT", 1]]
↳ app/helpers/sessions_helper.rb:3
(0.1ms) BEGIN
↳ app/controllers/users_controller.rb:28
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."id" != $2 LIMIT $3 [["email", "aaa@bbb.ccc"], ["id", 71], ["LIMIT", 1]]
↳ app/controllers/users_controller.rb:28
(0.2ms) ROLLBACK
↳ app/controllers/users_controller.rb:28
Redirected to http://localhost:3000/users/71
Completed 302 Found in 765ms (ActiveRecord: 1.0ms)
原因
編集時にpasswordの値を渡しておらず、passwordのバリデーションlength: { minimum: 6 }
にひっかかっていた。
解決方法
(1)パスワードのバリデーションに条件を加える。例)unless: :password_digest
(2)editを行うViewファイルに、hidden属性としてpasswordの値を渡す。
(3)そもそも実際のサービスでは、プロフィール編集時にpassword入力させる必要がある。(今回はさせていなかった)
解決に向けて試した事
ControllerのUpdate処理の前に、binding.pryを入れて値の確認(byebugでも可)
before_action :set_user,only:[:update]
def update
binding.pry
if @user.id != current_user.id
redirect_to root_path, notice: '他のアカウントから変更することはできません'
elsif @user.update(user_params)
redirect_to user_path(current_user.id), notice: 'プロフィール画像を更新しました'
else
redirect_to user_path(current_user.id), notice: 'プロフィール画像の更新に失敗しました'
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name,:email,:password,:password_confirmation,:image,:image_cache)
end
もう一度binding.pryが発火するまで操作する。
ターミナルでparamsを確認する。
pry(#<UsersController>)> params
=> <ActionController::Parameters {
"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"AxLyzK8R83er9WZjN3oYG72+146wLjSBytZ3TIc7G814vBkEKp3h6rfv6W8w2bCFz6Wm6Y5JpQKeoD6AaqBLFg==",
"user"=><ActionController::Parameters {
"email"=>"aaa@bbb.ccc",
"image"=>#<ActionDispatch::Http::UploadedFile:0x00007fba4861fad0 @tempfile=#
<Tempfile:/var/folders/v1/rm2pdthd0jg_brcdz1d64ht40000gn/T/RackMultipart20190615-10003-12vzwe0.JPG>,
@original_filename="RIMG0005.JPG",
@content_type="image/jpeg",
@headers="Content-Disposition: form-data; name=\"user[image]\"; filename=\"RIMG0005.JPG\"\r\nContent-Type: image/jpeg\r\n">
} permitted: false>,
"commit"=>"確定",
"controller"=>"users",
"action"=>"update",
"id"=>"71"
} permitted: false>
渡した値は問題無い事が確認できた。(と思っていた)
次にUpdateを実行してみる。
pry(#<UsersController>)> @user.update(user_params)
(0.3ms) BEGIN
↳ (pry):8
User Exists (1.7ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."id" != $2 LIMIT $3 [["email", "aaa@bbb.ccc"], ["id", 71], ["LIMIT", 1]]
↳ (pry):8
(0.3ms) ROLLBACK
↳ (pry):8
=> false
pry(#<UsersController>)>
やはりROLLBACKした。
次にバリデーション例外が発生していないか確認する。
pry(#<UsersController>)> @user.errors
=> #<ActiveModel::Errors:0x00007fba4ea78220
@base=
#<User:0x00007fba48b5dda8
id: 71,
name: "test",
email: "aaa@bbb.ccc",
password_digest: "$2a$10$xjr3B5Ch6TeV2o5P/96uRuenFEk3XxGDQ74s97rHubxcry4EKQETq",
created_at: Sat, 15 Jun 2019 19:36:55 JST +09:00,
updated_at: Sat, 15 Jun 2019 19:36:55 JST +09:00,
image: nil>,
@details={:password=>[{:error=>:blank}, {:error=>:too_short, :count=>6}]},
@messages={:password=>["を入力してください", "は6文字以上で入力してください"]}>
pry(#<UsersController>)> @user.errors.full_messages
=> ["パスワードを入力してください", "パスワードは6文字以上で入力してください"]
パスワードの値が無い事が原因だと判明した。
ちなみにimage: nil
と出ているが、実際には値が存在することが確認できる。
[9] pry(#<UsersController>)> @user.image
=> #<ImageUploader:0x00007fba4ea53998
@cache_id="1560597767-10003-0007-8003",
@cache_storage=#<CarrierWave::Storage::File:0x00007fba4879fa90 @cache_called=nil, @uploader=#<ImageUploader:0x00007fba4ea53998 ...>>,
@file=
#<CarrierWave::SanitizedFile:0x00007fba4ea521b0
@content=nil,
@content_type="image/jpeg",
@file="/Users/apple/workspace/insta_clone/public/uploads/tmp/1560597767-10003-0007-8003/RIMG0005.JPG",
@original_filename="RIMG0005.JPG">,
@filename="RIMG0005.JPG",
@format=nil,
@model=
以上です。