Devise の User モデルのパラメータを、Devise の Controller/View を使わずに更新してみることとします。今回は、実際に Controller と View を作って更新できるかどうかを確認します。
パスワード変更のための Controller と View の作成
例として、パスワード変更部分を作ります。パスワード変更部分ができればあとは同じように username も作れるかと思います。
パスワード変更時の方針として、変更したいパスワード、変更したいパスワードの確認、現在のパスワードを入力して、update_with_password を使って変更するものとします。
パラメータ | 説明 |
---|---|
password | 変更したあとのパスワード |
password_confirm | 変更したあとのパスワード(確認用) |
current_password | 現在のパスワード |
ルーティングの設計
Profile のときと同様に、DHH 流ルーティングでやっていきます。
1 2 3 4 5 6 7 8 9 10 11 12 |
Rails.application.routes.draw do resource :account, :only => [:show] do resource :name, :only => [:edit, :update], module: "accounts" resource :avatar, :only => [:edit, :update], module: "accounts" # ユーザ名、パスワード、email の変更 resource :username, :only => [:edit, :update], module: "accounts" resource :email, :only => [:edit, :update], module: "accounts" resource :password, :only => [:edit, :update], module: "accounts" end # あとは省略 end |
これで、account/password に対して GET と PATH/UPDATE すればパスワードの変更が行えます。
1 2 3 4 |
$ bundle exec rails routes | grep password edit_account_password GET /account/password/edit(.:format) accounts/passwords#edit account_password PATCH /account/password(.:format) accounts/passwords#update PUT /account/password(.:format) accounts/passwords#update |
パスワード変更 Controller の作成
Profile のときと同様に、 Controller を作成します。また、config/routes.rb に変更が加えられるので、それに関しては削除しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ bundle exec rails g controller accounts/passwords edit update create app/controllers/accounts/passwords_controller.rb route namespace :accounts do get 'passwords/edit' get 'passwords/update' end invoke erb create app/views/accounts/passwords create app/views/accounts/passwords/edit.html.erb create app/views/accounts/passwords/update.html.erb invoke test_unit create test/controllers/accounts/passwords_controller_test.rb invoke helper create app/helpers/accounts/passwords_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/accounts/passwords.coffee invoke scss create app/assets/stylesheets/accounts/passwords.scss $ vi config/routes.rb 以下を削除 - route namespace :accounts do - get 'passwords/edit' - get 'passwords/update' - end $ bundle exec rails routes | grep password edit_account_password GET /account/password/edit(.:format) accounts/passwords#edit account_password PATCH /account/password(.:format) accounts/passwords#update PUT /account/password(.:format) accounts/passwords#update |
app/controllers/accounts/passwords_controller.rb を編集します。ストロングパラメータとして :password, :password_confirmation, :current_password を受け付けて、これを用いて update_with_password を行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Accounts::PasswordsController < ApplicationController before_action :authenticate_user! def edit end def update if current_user.update_with_password(user_params) redirect_to account_path else render :edit end end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:password, :password_confirmation, :current_password) end end |
パスワード変更 View の作成
app/views/accounts/passwords/edit.html.erb を編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<div class="card col-sm-6 mt-5 mx-auto px-0"> <div class="card-header"> <h3>パスワードを変更する</h3> </div> <div class="card-body"> <%= form_with(model: current_user, url: account_password_path, method: :put, local: true) do |f| %> <div class="form-group"> <%= f.label :password, "変更後のパスワード", :class => "form-label" %> <%= f.password_field :password, autocomplete: "new-password", :class => "form-control" %> <% if @minimum_password_length %> <div class="small form-text text-muted">最低<%= @minimum_password_length %>文字以上</div> <% end %> </div> <div class="form-group"> <%= f.label :password_confirmation, "変更後のパスワード(確認)", :class => "form-label" %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password", :class=>"form-control" %> </div> <div class="form-group"> <%= f.label :current_password, "現在のパスワード", :class => "form-label" %> <%= f.password_field :current_password, autocomplete: "current-password", :class => "form-control" %> <div class="small form-text">変更のために現在のパスワードを入力してください。</div> </div> <div class="actions"> <%= f.submit "更新する", :class => "btn btn-primary btn-block" %> <%= link_to "キャンセルして戻る", :back, :class => "btn btn-secondary btn-block" %> </div> <% end %> </div> </div> |
動作確認
ここまででパスワード変更画面はできたはずですので、動作確認します。例によって rails サーバを起動して http://127.0.0.1:3000/account/password/edit を叩きます。
パスワードを変更すると、redirect 指定を無視してログイン画面に戻ったかと思います。
その他のパラメータの変更
参考までに載せておきます。
パスワード変更
コントローラ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Accounts::PasswordsController < ApplicationController before_action :authenticate_user! def edit end def update if current_user.update_with_password(user_params) redirect_to account_path else render :edit end end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:password, :password_confirmation, :current_password) end end |
View
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<div class="card col-sm-6 mt-5 mx-auto px-0"> <div class="card-header"> <h3>パスワードを変更する</h3> </div> <div class="card-body"> <%= form_with(model: current_user, url: account_password_path, method: :put, local: true) do |f| %> <div class="form-group"> <%= f.label :password, "変更後のパスワード", :class => "form-label" %> <%= f.password_field :password, autocomplete: "new-password", :class => "form-control" %> <% if @minimum_password_length %> <div class="small form-text text-muted">最低<%= @minimum_password_length %>文字以上</div> <% end %> </div> <div class="form-group"> <%= f.label :password_confirmation, "変更後のパスワード(確認)", :class => "form-label" %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password", :class=>"form-control" %> </div> <div class="form-group"> <%= f.label :current_password, "現在のパスワード", :class => "form-label" %> <%= f.password_field :current_password, autocomplete: "current-password", :class => "form-control" %> <div class="small form-text">変更のために現在のパスワードを入力してください。</div> </div> <div class="actions"> <%= f.submit "更新する", :class => "btn btn-primary btn-block" %> <%= link_to "キャンセルして戻る", :back, :class => "btn btn-secondary btn-block" %> </div> <% end %> </div> </div> |
email 変更
コントローラ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Accounts::EmailsController < ApplicationController before_action :authenticate_user! def edit end def update if current_user.update_with_password(user_params) redirect_to account_path else render :edit end end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:email, :current_password) end end |
View
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<div class="card col-sm-6 mt-5 mx-auto px-0"> <div class="card-header"> <h3>メールアドレスを変更する</h3> </div> <div class="card-body"> <%= form_with(model: current_user, url: account_email_path, method: :put, local: true) do |f| %> <div class="form-group"> <%= f.label :email, "変更後のメールアドレス", :class => "form-label" %> <%= f.text_field :email, autocomplete: "email", :class => "form-control" %> </div> <div class="form-group"> <%= f.label :current_password, "現在のパスワード", :class => "form-label" %> <%= f.password_field :current_password, autocomplete: "current-password", :class => "form-control" %> <div class="small form-text">変更のために現在のパスワードを入力してください。</div> </div> <div class="actions"> <%= f.submit "更新する", :class => "btn btn-primary btn-block" %> <%= link_to "キャンセルして戻る", :back, :class => "btn btn-secondary btn-block" %> </div> <% end %> </div> </div> |
あとは、account の show.html.erb で書く編集画面へのリンクをつけておきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<div class="card col-sm-10 mx-auto mt-5 px-0"> <div class="card-header bg-white"> <h2>アカウント情報</h2> </div> <div class="card-body"> <div class="row"> <div class="col-sm-8"> <table class="table"> <tbody> <tr> <td>名前:</td> <td><%= current_user.profile.name %></td> <td><%= link_to "編集", edit_account_name_path %></td> </tr> <tr> <td>ユーザID:</td> <td><%= current_user.username %></td> <td><%= link_to "編集", edit_account_username_path %></td> </tr> <tr> <td>メールアドレス:</td> <td><%= current_user.email %></td> <td><%= link_to "編集", edit_account_email_path %></td> </tr> <tr> <td>パスワード:</td> <td>(非表示)</td> <td><%= link_to "編集", edit_account_password_path %></td> </tr> <tr> <td>自己紹介:</td> <td><%= current_user.profile.description %></td> <td>編集</td> </tr> </tbody> </table> </div> <div class="col-sm-4"> <!-- アバターファイルの表示 --> <div class="account-profile-image d-flex flex-column"> <%= image_tag current_user.profile.avatar.to_s, :class => "float-center border mb-2 mx-auto" %> <%= link_to "アバターを変更", edit_account_avatar_path %> </div> </div> </div> </div> </div> |