Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
32
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

[Devise] パスワードを入力せずにユーザー情報を編集する

はじめに

deviseを使ってユーザーの登録情報を編集する際にデフォルトのままだと
パスワードの入力を求められます。しかし、一々ユーザーにパスワードの入力を
求めるのはユーザーフレンドリーではないので、修正していきます。

環境

ruby 2.5.3
rails 5.2.2
devise 4.6.0

Deviseを使う準備

アプリの作成

rails new devise

deviseのインストール

GEMFILE
gem 'devise'

上記を追加したらbundle installします。
次に、deviseのファイルを生成します。

rails generate devise:install

すると、次のメッセージが表示されますのでとりあえず
下記のメッセージ1~4の通りにセットアップしてみましょう。

Running via Spring preloader in process 3919
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

セットアップ

(1)

config/environments/development.rb
# 追記する
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

(2)
localhost:3000/にアクセスした時のページの設定を行います。
今のままだと何もページが作成されていないので、ここではPagesControllerを作ります。

ターミナル
rails generate controller Pages index
routes.rb
# get 'pages/index'
root 'pages#index'

これでrootパスの設定は完了です。

(3)
フラッシュメッセージを表示するようにviewを修正します。

application.html.erb
<body>
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
    <%= yield %>
 </body>

とりあえずこれでいいでしょう。

(4)
deviseのviewをカスタマイズするには以下のコマンドを実行して
viewファイルを作成する必要があります。

rails generate devise:views
Running via Spring preloader in process 4256
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/shared
      create    app/views/devise/shared/_error_messages.html.erb
      create    app/views/devise/shared/_links.html.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
      invoke  erb
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/email_changed.html.erb
      create    app/views/devise/mailer/password_change.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb

これでセットアップは完了です。

モデルの作成

登録情報を編集するユーザーを作成していきます。
まず、次のコマンドを実行します。

rails generate devise User
Running via Spring preloader in process 4296
      invoke  active_record
      create    db/migrate/20190211043147_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users

モデルとマイグレーションファイルは次のようになってます。

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
end
migration
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

ここでは、ユーザーのメールアドレスをパスワードの入力なしで、
変更することを目標とするので何も変更しないで、migrateします。

rails db:migrate

ユーザー情報を登録

まず、ユーザーを登録します。
登録画面にアクセスするためにルーティングを確認しましょう。

routes.rb
devise_for :user

上記がdeviseのルーティングを提供しています。

rails routes
Prefix Verb                      URI Pattern                                                                             Controller#Action
         new_user_session GET    /users/sign_in(.:format)                                                                 devise/sessions#new
             user_session POST   /users/sign_in(.:format)                                                                 devise/sessions#create
     destroy_user_session DELETE /users/sign_out(.:format)                                                                devise/sessions#destroy
        new_user_password GET    /users/password/new(.:format)                                                            devise/passwords#new
       edit_user_password GET    /users/password/edit(.:format)                                                           devise/passwords#edit
            user_password PATCH  /users/password(.:format)                                                                devise/passwords#update
                          PUT    /users/password(.:format)                                                                devise/passwords#update
                          POST   /users/password(.:format)                                                                devise/passwords#create
 cancel_user_registration GET    /users/cancel(.:format)                                                                  devise/registrations#cancel
    new_user_registration GET    /users/sign_up(.:format)                                                                 devise/registrations#new
   edit_user_registration GET    /users/edit(.:format)                                                                    devise/registrations#edit
        user_registration PATCH  /users(.:format)                                                                         devise/registrations#update
                          PUT    /users(.:format)                                                                         devise/registrations#update
                          DELETE /users(.:format)                                                                         devise/registrations#destroy
                          POST   /users(.:format)                                                                         devise/registrations#create
                     root GET    /                                                                                        pages#index
       rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create

パスワードを入力せずにユーザー情報を編集する

まず、編集画面にアクセスして、パスワードを入力せずに更新すると
次のようなエラーメッセージが表示されるかと思います。

Current password can't be blank

このpasswordのvalidationをスキップするためにdeviseをカスタマイズしていきます。

Controllerを生成する

deviseのcontrollerをカスタマイズするには、次のコマンドを実行して
自身のcontrollerを作成する必要があります。

rails generate devise:controllers users
Running via Spring preloader in process 4601
      create  app/controllers/users/confirmations_controller.rb
      create  app/controllers/users/passwords_controller.rb
      create  app/controllers/users/registrations_controller.rb
      create  app/controllers/users/sessions_controller.rb
      create  app/controllers/users/unlocks_controller.rb
      create  app/controllers/users/omniauth_callbacks_controller.rb
===============================================================================

Some setup you must do manually if you haven't yet:

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

===============================================================================

routes.rbを修正する

先ほど生成したcontrollerを利用するため次のように修正してください。

routes.rb
devise_for :users, controllers: { registrations: 'users/registrations' }

update_resourceメソッドをオーバーライドする

registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

  protected
  # 追記する
  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end

current_passwordフォームを削除する

views/devise/registrations/edit.html.erb
<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: "current-password" %>
 </div>

こちらのフォームを削除しましょう。

編集してみる

http://localhost:3000/users/editにアクセスして
メールアドレスを変更してみてください。
すると次のフラッシュメッセージが表示されるはずです。

Your account has been updated successfully.

これで、パスワードを入力しなくてもユーザーの登録情報を
編集することが可能になりました!

最後に

deviseはとても便利なのですが、カスタマイズするには色々修正が必要です。
いつかdevise大辞典作りたいな〜

参考

deviseのREADME.md

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
32
Help us understand the problem. What are the problem?