質問編集履歴

1 誤字訂正

moai891

moai891 score 9

2020/07/18 14:08  投稿

carrierwaveの画像投稿で、画像データがDBに登録されない(インスタンス変数に代入されない)
## 困っていること
carrierwave + mini_magick + deviseを用いてユーザー登録時にアバター画像を投稿できるようにしたいです。
長文となり恐れ入りますが、アドバイス頂ければ幸いです。よろしくお願いいたします。
## 課題に対するアクション
- binding.pryを用いたデバッグ
① ストロングパラメーターのうち、[:avatar]のみインスタンス変数@profileに渡っていないように見える
```
[1] pry(#<Users::RegistrationsController>)> @profile
=> #<Profile:0x00007fb1b7dd95a8
id: nil,
phonenumber: "1118883333",
old: 21,
job: 1,
experience: 1,
practice_time: 1,
detail: "よろしく",
club: "ホゲホゲ",
avatar: nil, //問題点。なぜかnil
user_id: nil,
created_at: nil,
updated_at: nil>
```
②ストロングパラメーターは適切なデータを受け取っていると考えられる
```
=> <ActionController::Parameters {"phonenumber"=>"1118883333", "old"=>"21", "job"=>"1", "experience"=>"1", "practice_time"=>"1", "detail"=>"よろしく", "club"=>"ホゲホゲ", "avatar"=>#<ActionDispatch::Http::UploadedFile:0x00007fb1b7de7888 @tempfile=#<Tempfile:/var/folders/l9/g98ryfjs4730gx0slq67713r0000gn/T/RackMultipart20200718-27218-1f1z01b.png>, @original_filename="7071b4262c632dc0e7c7660f15459fba.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"profile[avatar]\"; filename=\"7071b4262c632dc0e7c7660f15459fba.png\"\r\nContent-Type: image/png\r\n">} permitted: true>
```
③@profile.avatarでは画像データが代入されている
```
=> #<AvatarUploader:0x00007fb1b7dcaff8
@cache_id="1595048033-27925243257579-0005-8319",
@cache_storage=#<CarrierWave::Storage::File:0x00007fb1b7dc2b28 @cache_called=nil, @uploader=#<AvatarUploader:0x00007fb1b7dcaff8 ...>>,
@file=
 #<CarrierWave::SanitizedFile:0x00007fb1b7dc9b58
  @content=nil,
  @content_type="image/png",
  @file="/Users/teranishiyusuke/projects/badsuru/public/uploads/tmp/1595048033-27925243257579-0005-8319/7071b4262c632dc0e7c7660f15459fba.png",
  @original_filename="7071b4262c632dc0e7c7660f15459fba.png">,
@filename="7071b4262c632dc0e7c7660f15459fba.png",
@identifier=nil,
@model=
 #<Profile:0x00007fb1b7dd95a8
  id: nil,
  phonenumber: "1118883333",
  old: 21,
  job: 1,
  experience: 1,
  practice_time: 1,
  detail: "よろしく",
  club: "ホゲホゲ",
  avatar: nil,
  user_id: nil,
  created_at: nil,
  updated_at: nil>,
@mounted_as=:avatar,
@original_filename="7071b4262c632dc0e7c7660f15459fba.png",
@staged=true,
@versions={}>
```
④avatarがnilだからか、@user.save時に、avatarに対するSQL文が発行されていないように見える
```
[4] pry(#<Users::RegistrationsController>)> exit
  (11.0ms) BEGIN
 ↳ app/controllers/users/registrations_controller.rb:34:in `create_profile'
 User Exists? (13.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'raaa@r.com' LIMIT 1
 ↳ app/controllers/users/registrations_controller.rb:34:in `create_profile'
 User Create (17.4ms) INSERT INTO `users` (`nickname`, `email`, `encrypted_password`, `created_at`, `updated_at`) VALUES ('aabbcc', 'raaa@r.com', '$2a$11$HMGyw2YYP9qDzQKbh369PeCcnxGAB5dxLIUO/vwnvqzuiRqK9xwcS', '2020-07-18 04:59:38.775316', '2020-07-18 04:59:38.775316')
 ↳ app/controllers/users/registrations_controller.rb:34:in `create_profile'
 Profile Create (16.6ms) INSERT INTO `profiles` (`phonenumber`, `old`, `job`, `experience`, `practice_time`, `detail`, `club`, `user_id`, `created_at`, `updated_at`) VALUES ('1118883333', 21, 1, 1, 1, 'よろしく', 'ホゲホゲ', 4, '2020-07-18 04:59:38.809212', '2020-07-18 04:59:38.809212')
 ↳ app/controllers/users/registrations_controller.rb:34:in `create_profile'
  (18.7ms) COMMIT
 ↳ app/controllers/users/registrations_controller.rb:34:in `create_profile'
No template found for Users::RegistrationsController#create_profile, rendering head :no_content
Completed 204 No Content in 344980ms (ActiveRecord: 76.7ms | Allocations: 56585)
```
## 詳細なコード
- registration_controller.rb
```registration_controller.rb
# frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
 # before_action :configure_sign_up_params, only: [:create]
 # before_action :configure_account_update_params, only: [:update]
 # GET /resource/sign_up
 def new
   @user = User.new
 end
 # POST /resource
 def create
   @user = User.new(sign_up_params)
   unless @user.valid?
     flash.now[:alert] = @user.errors.full_messages
     render :new and return
   end
   session["devise.regist_data"] = {user: @user.attributes}
   session["devise.regist_data"][:user]["password"] = params[:user][:password]
   @profile = @user.build_profile
   render :new_profile
 end
 def create_profile
   @user = User.new(session["devise.regist_data"]["user"])
   @profile = Profile.new(profile_params)
   unless @profile.valid?
     flash.now[:alert] = @user.errors.full_messages
     render :new_profile and return
   end
   @user.build_profile(@profile.attributes)
   binding.pry
   @user.save
   session["devise.regist_data"]["user"].clear
   sign_in(:user, @user)
 end
 # GET /resource/edit
 # def edit
 #  super
 # end
 # PUT /resource
 # def update
 #  super
 # end
 # DELETE /resource
 # def destroy
 #  super
 # end
 # GET /resource/cancel
 # Forces the session data which is usually expired after sign
 # in to be expired now. This is useful if the user wants to
 # cancel oauth signing in/up in the middle of the process,
 # removing all OAuth session data.
 # def cancel
 #  super
 # end
 protected
 def profile_params
   params.require(:profile).permit(:phonenumber, :old, :job, :experience, :practice_time, :detail, :club, :avatar)
 end
 
 # If you have extra params to permit, append them to the sanitizer.
 # def configure_sign_up_params
 #  devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
 # end
 # If you have extra params to permit, append them to the sanitizer.
 # def configure_account_update_params
 #  devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
 # end
 # The path used after sign up.
 # def after_sign_up_path_for(resource)
 #  super(resource)
 # end
 # The path used after sign up for inactive accounts.
 # def after_inactive_sign_up_path_for(resource)
 #  super(resource)
 # end
end
```
- profile.rb
```profile.rb
class Profile < ApplicationRecord
 belongs_to :user, optional: true
 validates  :old, :job, :experience, :phonenumber, :practice_time, presence: true
 mount_uploader :avatar, AvatarUploader
end
```
- avatar_uploader.rb
```avatar_uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
 # Include RMagick or MiniMagick support:
 # include CarrierWave::RMagick
 include CarrierWave::MiniMagick
 # Choose what kind of storage to use for this uploader:
 storage :file
 # storage :fog
 # Override the directory where uploaded files will be stored.
 # This is a sensible default for uploaders that are meant to be mounted:
 def store_dir
   "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
 end
 # Provide a default URL as a default if there hasn't been a file uploaded:
 # def default_url(*args)
 #  # For Rails 3.1+ asset pipeline compatibility:
 #  # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
 #
 #  "/images/fallback/" + [version_name, "default.png"].compact.join('_')
 # end
 # Process files as they are uploaded:
 # process scale: [200, 300]
 #
 # def scale(width, height)
 #  # do something
 # end
 # Create different versions of your uploaded files:
 # version :thumb do
   process resize_to_fit: [50, 50]
 # end
 # Add a white list of extensions which are allowed to be uploaded.
 # For images you might use something like this:
 # def extension_whitelist
 #  %w(jpg jpeg gif png)
 # end
 # Override the filename of the uploaded files:
 # Avoid using model.id or version_name here, see uploader/store.rb for details.
 # def filename
 #  "something.jpg" if original_filename
 # end
end
```
- 登録フォーム
```profile_new.erb.html
<h2>住所情報登録</h2>
<%= form_for @profile do |f| %>
 <%= render "devise/shared/error_messages", resource: @profile %>
 <div class="field">
   <%= f.label :phonenumber %><br />
   <%= f.text_field :phonenumber %>
 </div>
 <div class="field">
   <%= f.label :old %><br />
   <%= f.text_field :old %>
 </div>
 <div class="field">
   <%= f.label :job %><br />
   <%= f.text_field :job %>
 </div>
 <div class="field">
   <%= f.label :experience %><br />
   <%= f.text_field :experience %>
 </div>
 <div class="field">
   <%= f.label :practice_time %><br />
   <%= f.text_field :practice_time %>
 </div>
 <div class="field">
   <%= f.label :detail %><br />
   <%= f.text_field :detail %>
 </div>
 <div class="field">
   <%= f.label :club %><br />
   <%= f.text_field :club %>
 </div>
 <div class="field"> //画像投稿欄
   <%= f.label :avatar %><br />
   <%= f.file_field :avatar , class: "avatar"%>
 </div>
 <div class="actions">
   <%= f.submit "Sign up" %>
 </div>
<% end %>
<%= render "devise/shared/links" %>
```
  • Ruby

    15082 questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • MySQL

    10260 questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • Ruby on Rails 6

    963 questions

    Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る