railsのdeviseを使ってUserモデルに一対一のリレーションシップでユーザー情報を紐付ける

# 今回やりたかったこと
認証情報とユーザー情報を切り分けたかった。
セキュリティー上の観点とユーザー情報が増えれば増えるほど処理が重くなるかなーッと思って今回は以下の内容で対応。（あんまり意味ないのかなー）
ユーザー認証は「devise」
ユーザー情報は別テーブルの「userinfo」に格納する

#前提条件
各種バージョン

- ruby 2.5.1
- Rails 5.2.0

```
$ bundle install
```

「devise」を記述済みで上記コマンドを実行済み

# 認証の設定

```ruby:/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base

  # CSRF保護をオンにする以下の1行を有効にします。
  protect_from_forgery with: :exception
  # ログイン済ユーザーのみにアクセスを許可する
  before_action :configure_permitted_paramaters, if: :devise_controller?

  private
  def configure_permitted_paramaters
#devise_parameter_sanitizer = 許可するパラメータを追加（railsのバージョンによって書き方が異なるので注意）
  	devise_parameter_sanitizer.permit(:sign_up, keys: [:userinfo_attributes => [:user_id, :name, :body]])
  	devise_parameter_sanitizer.permit(:account_update, keys: [:userinfo_attributes => [:user_id, :name, :body]])
  end

end
```
- [【Rails】Deviseでのstrong parameters指定はdevise_parameter_sanitizer.forではなくdevise_parameter_sanitizer.permitを使うようになったらしい](https://qiita.com/ry023/items/c6a469f65615f796be45)
- [Rails+Deviseでユーザー名でサインインできるようにする](http://blog.panicblanket.com/archives/2097)


```ruby:app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
#
# 省略
#

#以下を追記

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up) do |params|
      params.permit(:email, :password, :password_confirmation, :current_password,
                    userinfo_attributes: [:user_id,:name, :body])
    end
  end

  # If you have extra params to permit, append them to the sanitizer.
  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update) do |params|
      params.permit(:email, :password, :password_confirmation, :current_password,
                    userinfo_attributes: [:user_id, :name, :body])
    end
  end
end
```



```ruby:/app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable
  #has_one = 関連付け  inverse_of = 双方の関連付け
  has_one :userinfo, dependent: :destroy, inverse_of: :user

  accepts_nested_attributes_for :userinfo, update_only: true
end
```

[Active Record の関連付け (アソシエーション)](https://railsguides.jp/association_basics.html)
[ActiveRecordのコールバックの順序・コールバック内のロールバック処理について]
(https://blog.toshimaru.net/active-record-callbacks/)

# userとuserinfoのリレーションを作成

```ruby:/db/migrate/xxxxxxx_create_userinfos.rb
class CreateUserinfos < ActiveRecord::Migration[5.2]
  def change
    create_table :userinfos do |t|
      t.references :user, null: false
      t.string :name
      t.text :body

      t.timestamps
    end
  end
end
```

マイグレートを実行

```
$ rails db:migrate
```
userモデルとの関連付け

```ruby:/app/models/userinfo.rb
class Userinfo < ApplicationRecord
 belongs_to :user, inverse_of: :userinfo, optional: true
end
```

各view側の設定

```erb:rails:/app/views/users/registrations/new.html.erb
<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <%= f.fields_for :userinfo, resource.build_userinfo || Userinfo.new do |info| %>
  <%= info.label :name %>
  <%= info.text_field :name%>
  <% end %>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "users/shared/links" %>
```

```erb:rails:/app/views/users/registrations/edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "off" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "off" %>
  </div>

  <%= f.fields_for :userinfo do |info| %>
  <%= info.label :name %>
  <%= info.text_field :name%>
  <% end %>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>

<%= link_to "Back", :back %>

```

## 参考にさせていただいた記事

[deviseで作成したUserモデルでhas_oneなリレーションを組む](https://qiita.com/ReiShimizu/items/a343b3496cf90c3b6b97)