8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Rails】UserテーブルをUPDATEした時にROLLBACKした原因と解決方法

Last updated at Posted at 2019-06-15

今回の経緯

Userテーブルのemailの値とimageファイルの変更に失敗する。
次の画像は、実際にUserテーブルを更新した際に上手く動作しなかった時の映像です。
testdouga.mov.gif

ターミナルは次のような処理が走っています。

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=

以上です。

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?