はじめに
やりたいこと
- deviseを用いてUser登録
- 子モデルProfileにプロフィール画像等のデータを扱わせる
- userレコードの生成と同時にprofileレコードも生成する
- profileレコードにデフォルトでデータを入れる
やる理由
- できるだけdeviseを触りたくない
- profileレコードを同時生成してnew&createアクションを省略
- デフォルトでデータを入れることで空カラムによる厄介事を回避
やってみて
思ったより簡単にできました。特にimage(プロフィール画像)を生成時にアタッチしておくのは今後も使えそうなので備忘しておきます。
参考にした記事
url4u.jp > Profile モデルを定義して Devise の User に紐付ける
手順
前提として
- deviseのインストール
- 各モデル(User、Profile)の作成&マイグレーション
- deviseのストロングパラメーターの設定
は完了しているものとして進めます。
アソシエーションを記述
まずは各モデルにアソシエーションを記述します。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :profile, dependent: :destroy
end
dependent: :destroyを付与してuserレコードの削除に伴ってprofileが削除されるようにしました。
class Profile < ApplicationRecord
belongs_to :user
has_one_attached :image
end
profileモデルにはActive Storageを使ってプロフィール画像を持たせるので、そちらのアソシエーションも記述しました。詳細は後述します。
これで各モデル側の準備はできたので、次はdeviseコントローラーを編集してuserレコード生成時にprofileレコードが自動的に生成される仕組みを作ります。
devise controller 生成
devise関連のコントローラーを生成します。
% rails g devise:controllers users
次に、こちらのコマンドによって生成されたregistrations_controller.rbを編集します。
…の前に、忘れずにルーティングを記述しておきます。
Rails.application.routes.draw do
devise_for :users, controllers: {
registrations: 'users/registrations'
}
end
このルーティングを書いておかないとregistrations_controllerに編集した内容が反映されません。
##registration_controllerの編集
そして本題の「registrations_controller.rbの編集」ですが、デフォルトの記述がありますので、必要な部分のコメントアウトを外して編集していきます。
class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
〜中略〜
# POST /resource
def create
super
resource.build_profile
resource.save
end
# GET /resource/edit
〜中略〜
end
createメソッドの中にbuild_profileとsaveを記述することで、userレコードのcreate時にprofileレコードが保存されるようになりました。
superとは
親クラスで定義されている同名のメソッドを呼ぶことが出来るメソッド
=> 参照 : Rubyの継承とオーバーライドについてまとめてみた
こちらの記事がわかりやすく、勉強させていただきました
resourceとは
今回編集したUsers::RegistrationsControllerはDevise::ResistrationsControllerの子クラスになります。
resouseは親クラスDevise::ResistrationsControllerで定義されている変数?なので、そちらを見に行かないと実態はわかりません。
=> 参照 : [Rails][devise] registrations_controllerのcreateを読み解く
応用① 特定のカラムにデータを入れて生成する
例えば「プロフィールの自己紹介文をデフォルトで入れておきたい!」みたいなときに使えます。
class Users::RegistrationsController < Devise::RegistrationsController
〜中略〜
def create
super
resource.build_profile
resource.profile.intro = 'プロフィールを編集しよう!'
resource.save
end
〜中略〜
end
こちらの記述でintroカラムに初期データを入れることができました。
NOT NULL制約を設定している場合もこれで回避できます(たぶん)
応用② 画像をアタッチして生成する
僕が一番やってよかったと思ったのがデフォルト画像を設定したことです。
今つくっているアプリはいろいろなページでアバターを表示させているのですが、当初はimage=nilをすべて条件分岐で対応しようと思っていました(無知ってこわい…)
ダミー画像を初期値で入れておくことで、無駄な記述が減るし、サインアップ直後のユーザーさんがイメージしやすい見栄えになったし、良いこと尽くしでした。
注)imageはActive Storageで紐付けしています。
Active Storage の設定方法はこちら
=> 【Ruby/Rails】Active Storage 初期設定マニュアル
class Users::RegistrationsController < Devise::RegistrationsController
〜中略〜
def create
super
resource.build_profile
resource.profile.image.attach(io: File.open('ディレクトリ名/ファイル名'), filename: 'ファイル名') resource.save
end
〜中略〜
end
こちらの記述でActive Storageにデータが保存されます。
ちなみに僕の場合はこんな感じ
class Users::RegistrationsController < Devise::RegistrationsController
〜 中略 〜
def create
super
resource.build_profile
resource.profile.image.attach(io: File.open('public/images/human_icon.png'), filename: 'human_icon.png')
end
〜 中略 〜
end
彼を初期値に設定しました。かわいい。
おわりに
初めてQiitaで記事を書きました。
これから備忘録を中心に、Qiitaに投稿したいと思います。
初学者故、間違っている点/非効率な点が多々あると思いますので、お気づきになったらご指摘いただけると嬉しいです。
もし「これは使える」「わかりやすい」と思った方がいらっしゃいましたら、ぜひLGTMしてください!飛び跳ねてよろこびます。
またプログラミング初学者仲間のみなさん、初学者同士ぜひ絡んでください!!
最後までお読みいただいてありがとうございました!
✔︎