Userモデルに子モデルを効率よく紐付ける手順

# はじめに
## やりたいこと
- deviseを用いてUser登録
- 子モデルProfileにプロフィール画像等のデータを扱わせる
- userレコードの生成と同時にprofileレコードも生成する
- profileレコードにデフォルトでデータを入れる

## やる理由
- できるだけdeviseを触りたくない
- profileレコードを同時生成してnew&createアクションを省略
- デフォルトでデータを入れることで空カラムによる厄介事を回避

## やってみて
思ったより簡単にできました。特にimage（プロフィール画像）を生成時にアタッチしておくのは今後も使えそうなので備忘しておきます。

## 参考にした記事
[url4u.jp > Profile モデルを定義して Devise の User に紐付ける](https://url4u.jp/rails-523-devise-profile-association/)

# 手順

前提として

1. deviseのインストール
2. 各モデル（User、Profile）の作成＆マイグレーション
3. deviseのストロングパラメーターの設定

は完了しているものとして進めます。
## アソシエーションを記述
まずは各モデルにアソシエーションを記述します。

```ruby:models/user.rb
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が削除されるようにしました。

```ruby:models/profile.rb
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を編集します。
…の前に、忘れずにルーティングを記述しておきます。

```ruby:routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
end
```

このルーティングを書いておかないとregistrations_controllerに編集した内容が反映されません。

##registration_controllerの編集
そして本題の「registrations_controller.rbの編集」ですが、デフォルトの記述がありますので、必要な部分のコメントアウトを外して編集していきます。


```ruby:controllers/users/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の継承とオーバーライドについてまとめてみた](https://rails-study.net/extend/)
>こちらの記事がわかりやすく、勉強させていただきました

resourceとは

> 今回編集したUsers::RegistrationsControllerはDevise::ResistrationsControllerの子クラスになります。
> resouseは親クラスDevise::ResistrationsControllerで定義されている変数？なので、そちらを見に行かないと実態はわかりません。
> => 参照 : [[Rails][devise] registrations_controllerのcreateを読み解く](https://qiita.com/after4649/items/797fa2ccd9c119cc18dc)


## 応用①　特定のカラムにデータを入れて生成する

例えば「プロフィールの自己紹介文をデフォルトで入れておきたい！」みたいなときに使えます。

```ruby:controllers/users/registrations_controller.rb
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 初期設定マニュアル](https://qiita.com/tatsuhiko-nakayama/items/3b113b4789e799cfd824)

```ruby:controllers/users/registrations_controller.rb
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にデータが保存されます。


ちなみに僕の場合はこんな感じ

```ruby:controllers/users/registrations_controller.rb
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
```
human_icon.png
<img width="125" alt="![human-iconのコピー.png]" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/771826/c2dafeca-509d-d897-8b8b-989793b843a8.png">


彼を初期値に設定しました。かわいい。


# おわりに
初めてQiitaで記事を書きました。
これから備忘録を中心に、Qiitaに投稿したいと思います。

初学者故、間違っている点／非効率な点が多々あると思いますので、お気づきになったらご指摘いただけると嬉しいです。

もし「これは使える」「わかりやすい」と思った方がいらっしゃいましたら、ぜひLGTMしてください！飛び跳ねてよろこびます。

またプログラミング初学者仲間のみなさん、初学者同士ぜひ絡んでください！！
最後までお読みいただいてありがとうございました！

✔︎