[Rails][devise] registrations_controllerのcreateを読み解く

# やること

deviseのregistrations_controller#createを
オーバライドしようと思ったので、久々に読み返しました。

元々のコードが何をしようとしているのか
備忘録として念のため残しておきます。


# 元コード

devise registrations_controller
https://github.com/plataformatec/devise/blob/e3a00b27d19ba995891d7dd92394fe2900a789c2/app/controllers/devise/registrations_controller.rb

```ruby:devise/registrations_controller
  def create
    build_resource(sign_up_params)

    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource
    end
  end
```

# コメントをいれます
```ruby:registrations_controller
  def create
    # ここでUser.new（と同等の操作）を行う
    build_resource(sign_up_params)

    # ここでUser.save（と同等の操作）を行う
    resource.save

    # ブロックが与えられたらresource(=User)を呼ぶ
    yield resource if block_given?
    if resource.persisted?
    # 先程のresource.saveが成功していたら
      if resource.active_for_authentication?
      # confirmable/lockableどちらかのactive_for_authentication?がtrueだったら
        # flashメッセージを設定
        set_flash_message! :notice, :signed_up
        # サインアップ操作
        sign_up(resource_name, resource)
        # リダイレクト先を指定
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        # sessionを削除
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
    # 先程のresource.saveが失敗していたら
      # passwordとpassword_confirmationをnilにする
      clean_up_passwords resource
      # validatable有効時に、パスワードの最小値を設定する
      set_minimum_password_length
      respond_with resource
    end
  end
```


以下補足です。


# expire_data_after_sign_in!

ここでは、`devise`から始まる名前のキーを`session.keys`から探し出し
そのキーに対して`session.delete(キー名)`を行います。
https://github.com/plataformatec/devise/blob/715192a7709a4c02127afb067e66230061b82cf2/lib/devise/controllers/sign_in_out.rb#L108

```ruby:devise/sign_in_out.rb
      def expire_data_after_sign_in!
        # session.keys will return an empty array if the session is not yet loaded.
        # This is a bug in both Rack and Rails.
        # A call to #empty? forces the session to be loaded.
        session.empty?
        session.keys.grep(/^devise\./).each { |k| session.delete(k) }
      end
```

コメントにあるとおり、セッションが読み込まれない間はRackとRailsのバグにより
session.keysは空の配列を返すので、empty?を呼ぶ際にセッションの読み込みを強制します。

# clean_up_passwords

これは、上述したとおり。
https://github.com/plataformatec/devise/blob/55e726e4a7a54be81c052100b5a7976dabfc90fe/lib/devise/models/database_authenticatable.rb#L72

```ruby:
     def clean_up_passwords
       self.password = self.password_confirmation = nil
     end
```

# set_minimum_password_length
ここでは`@minimum_password_length`にパスワードの長さの最小値を指定します。
（validationが6~72文字なら6文字、15〜43文字なら15文字。）
この`@minimum_password_length`はどこで使われているかというと、
`registrations/newのView`にて使われています。
https://github.com/plataformatec/devise/blob/76b87dc0e83736cf16e3ffbc465fcd8ee3c06d46/app/views/devise/registrations/new.html.erb#L13

```ruby:registrations/new.html.erb
  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>
```

`@minimum_password_length`が設定されていれば`6 characters minimum`のように、
`パスワードは最低何文字にしてください`というメッセージの「何文字」にあたる部分に使われます。


<br>

間違いがあるかもしれません。
おわり