このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。
https://github.com/hkob/hkob_blog
はじめに
Rails Tips の 75 回目です。昨日は、OAuth2 の導入に失敗しました。一度、ローカルの認証で正しく動くようになってから、OAuth2 は再挑戦しようと思います。期待していた人すみません。
git revert
昨日の作業は事前にコミットしてしまったので、git revert で打ち消しコミットを作成しました。こういうこともたまにやつておかないと忘れるので、これも記録しておきます。
git revert f10c24e48e481e1a2676746b6e86ef748fe491ea [main 06398ee] Revert "OAuth2 認証の実装: 小林研 Rails Tips (74)" 17 files changed, 1 insertion(+), 793 deletions(-) delete mode 100644 app/controllers/users/omniauth_callbacks_controller.rb delete mode 100644 app/models/user.rb delete mode 100644 config/credentials/development.yml.enc delete mode 100644 config/initializers/devise.rb delete mode 100644 config/initializers/omniauth.rb delete mode 100644 config/locales/devise.en.yml delete mode 100644 db/migrate/20240211070843_devise_create_users.rb delete mode 100644 lib/custom_authentication_failure.rb delete mode 100644 spec/models/user_spec.rb delete mode 100644 spec/requests/users/omniauth_callbacks_spec.rb
とりあえずまず、devise でローカルのログインをしっかり実装してから、OAuth2 に挑戦することにしましょう。せっかくこれまで i18n も使っているので、i18n 版も入れておきましょう。記述したら bundle しておきます。
gem "devise" gem "devise-i18n"
devise をインストールします。
$ bin/rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Depending on your application's configuration some manual setup may be required: 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. * Required for all applications. * 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" * Not required for API-only Applications * 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> * Not required for API-only Applications * 4. You can copy Devise views (for customization) to your app by running: rails g devise:views * Not required * ===============================================================================
devise.en.yml は作られていますが、ja 版がありません。以下のコマンドで作っておきます。ちょっとファイル名と中身が違うようですね。日本語しか使わないので、en はそのままでいいでしょう。
$ bin/rails g devise:i18n:locale ja create config/locales/devise.views.ja.yml
リベンジで User を再度作成します。
$ bin/rails g devise User invoke active_record create db/migrate/20240212112549_devise_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb insert app/models/user.rb route devise_for :users
app/models/user.rb に使用する機能を登録します。デフォルトのものに trackable を追加してみました。
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :trackable end
trackable を追加したので、それに関するものを追加しました。また、name を表示したいので email の前に登録しています。name にも index を振っておきます。
# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[7.1] def change create_table :users do |t| ## Database authenticatable t.string :name, null: false, default: "" 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, :name, unique: true 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
migration しておきます。一度ファイルを戻してしまったので、データベースを一度削除してから migrate しました。
$ bin/rails db:drop Dropped database 'hkob_blog_development' Dropped database 'hkob_blog_test' $ bin/rails db:create Created database 'hkob_blog_development' Created database 'hkob_blog_test' $ bin/rails db:migrate == 20240122091842 CreateArticles: migrating =================================== -- create_table(:articles) -> 0.0079s == 20240122091842 CreateArticles: migrated (0.0079s) ========================== == 20240131125824 CreateComments: migrating =================================== -- create_table(:comments) -> 0.0081s == 20240131125824 CreateComments: migrated (0.0081s) ========================== == 20240208115326 AddStatusToArticle: migrating =============================== -- add_column(:articles, :status, :string, {:null=>false}) -> 0.0015s == 20240208115326 AddStatusToArticle: migrated (0.0016s) ====================== == 20240208115356 AddStatusToComment: migrating =============================== -- add_column(:comments, :status, :string, {:null=>false}) -> 0.0135s == 20240208115356 AddStatusToComment: migrated (0.0136s) ====================== == 20240212112549 DeviseCreateUsers: migrating ================================ -- create_table(:users) -> 0.0084s -- add_index(:users, :name, {:unique=>true}) -> 0.0012s -- add_index(:users, :email, {:unique=>true}) -> 0.0036s -- add_index(:users, :reset_password_token, {:unique=>true}) -> 0.0018s == 20240212112549 DeviseCreateUsers: migrated (0.0151s) =======================
通常であれば、views は作らなくてもいいのですが、今回 name を追加したため、これをフォームに追加する必要があります。user と admin など異なるモデルごとにログイン画面を変更したい場合には、そのモデル名を記述します。今回は user のみとする予定なので、devise 共通の views を作ります。
$ bin/rails g devise:views 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
それぞれの view が devise ネームスペースの下に作成されました。ただし、erb になっています。以前使った erb2haml で haml に変更しておきましょう。
> bin/rails haml:erb2haml -------------------------------------------------------------------------------- Generating HAML for app/views/devise/confirmations/new.html.erb... Generating HAML for app/views/devise/mailer/confirmation_instructions.html.erb... Generating HAML for app/views/devise/mailer/email_changed.html.erb... Generating HAML for app/views/devise/mailer/password_change.html.erb... Generating HAML for app/views/devise/mailer/reset_password_instructions.html.erb... Generating HAML for app/views/devise/mailer/unlock_instructions.html.erb... Generating HAML for app/views/devise/passwords/edit.html.erb... Generating HAML for app/views/devise/passwords/new.html.erb... Generating HAML for app/views/devise/registrations/edit.html.erb... Generating HAML for app/views/devise/registrations/new.html.erb... Generating HAML for app/views/devise/sessions/new.html.erb... Generating HAML for app/views/devise/shared/_error_messages.html.erb... Generating HAML for app/views/devise/shared/_links.html.erb... Generating HAML for app/views/devise/unlocks/new.html.erb... -------------------------------------------------------------------------------- HAML generated for the following files: app/views/devise/confirmations/new.html.erb app/views/devise/mailer/confirmation_instructions.html.erb app/views/devise/mailer/email_changed.html.erb app/views/devise/mailer/password_change.html.erb app/views/devise/mailer/reset_password_instructions.html.erb app/views/devise/mailer/unlock_instructions.html.erb app/views/devise/passwords/edit.html.erb app/views/devise/passwords/new.html.erb app/views/devise/registrations/edit.html.erb app/views/devise/registrations/new.html.erb app/views/devise/sessions/new.html.erb app/views/devise/shared/_error_messages.html.erb app/views/devise/shared/_links.html.erb app/views/devise/unlocks/new.html.erb -------------------------------------------------------------------------------- Would you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n) y Deleting original .erb files. -------------------------------------------------------------------------------- Task complete!
おわりに
ちょっと長くなってしまったので、この続きは明日に回します。ログイン自体はあっという間に終わると思うので、その後、記事やコメントにユーザへの関連を追加してみます。