【Rails】devise_invitable 使ってみる
はじめに
業務でdevise_invitable
gemを使っているプロジェクトがあるが、自分で実装したことはなかったためカスタマイズなしで手順を確認しました。
環境
前提
- rails newした後にdeviseをインストールし、Userを作成。認証しているUserのみアクセスできるUser一覧画面のみ作成済
- letter_openerを入れ、メールが確認できるように設定済
そこからdevise_invitableを導入する手順です。
手順
① gemfileに追加
gem 'devise_invitable'
② インストール
$ rails g devise_invitable:install
③ deviseで作成したモデルでinvitableが使えるようにする
$ rails g devise_invitable User $ rails db:migrate
- マイグレーションファイル
xxxxxxxxxx_devise_invitable_add_to_users.rb
が作成される。invitableで使用するカラムがUsersテーブルに追加される - Userモデルに
devise :invitable
が挿入される
この時点でrails routes
で確認すると、invitationのパスが設定されている
$ rails routes ... accept_user_invitation GET /users/invitation/accept(.:format) devise/invitations#edit remove_user_invitation GET /users/invitation/remove(.:format) devise/invitations#destroy new_user_invitation GET /users/invitation/new(.:format) devise/invitations#new user_invitation PATCH /users/invitation(.:format) devise/invitations#update PUT /users/invitation(.:format) devise/invitations#update POST /users/invitation(.:format) devise/invitations#create
④ viewを作成
rails g devise_invitable:views invoke DeviseInvitable::Generators::MailerViewsGenerator exist app/views/devise/mailer create app/views/devise/mailer/invitation_instructions.html.erb create app/views/devise/mailer/invitation_instructions.text.erb invoke simple_form_for create app/views/devise/invitations create app/views/devise/invitations/edit.html.erb create app/views/devise/invitations/new.html.erb
⑤ ユーザーを作成してみる
Userモデルからinviteメソッドを使用して、Userを作成しつつ招待メールを送信。
$ rails c > User.invite!(email: 'makky@example.com')
inviteメソッドから招待メールが送信される
招待リンクから遷移するとパスワード入力が入力できる
パスワードを設定して、rootに設定したページに遷移
Userが作成され、ログイン済になった!
【Rails】名前空間のあるモデルのspec
はじめに
前回名前空間のあるモデルを作成しました。
【Rails】テーブル名にプレフィックスを付与・ネームスペース付きのモデルを作成 - まっきーの学習記録
どうやってスペックを書くのか調べたので、まとめます。
方法
本記事でproject
は名前空間の名前です。
それぞれのアプリで置き換えてください。
(1つのアプリに複数プロジェクトを共存させるという目的があったため、projectとしています。)
Factoryの作成
spec/factories/users.rbを作るようなところ、spec/factories/project/users.rbを作成。
classに名前空間付きのクラス名を渡す。
そのほかは通常の書き方でOK。
FactoryBot.define do factory :project_user, class: 'Project::User' do ... end end
System Spec 等で呼び出し
spec側での呼び出しはfactory名をそのまま呼び出すだけなので、通常通りでOK。
let(:user) { FactoryBot.create(:project_user, email: 'test@example.com') }
終わりに
Factoryを作成する時にclass名を指定してあげるだけで良いので想像以上に簡単でした。
ちなみにディレクトリ構造のイメージは以下のような感じです。 ご参考までに。
spec └factories └projectA └users.rb └admins.rb └projectB └users.rb └admins.rb └system └projectA └projectB └...(他のspec等)
【Rails】テーブル名にプレフィックスを付与・ネームスペース付きのモデルを作成
はじめに
ある2つのプロジェクトを1つのプロジェクトとして統合して管理したいため、Railsアプリの各ディレクトリ内を以下のようにプロジェクト毎に取り扱いということがありました。
models └ProjectA └User.rb └Admin.rb └... └ProjectB └User.rb └Admin.rb └...
そのためテーブル名にプレフィックスをつけて管理、モデルもそれに対応する必要があり、この記事を書いています。
ネームスペース付きのモデルを新規で作成してみる
新規でテーブル名にプレフィックスを付与・ネームスペース付きのモデルを作成する場合は以下のようにネームスペース名::
をつけてモデルを作成します。
rails g model Project::User email:string
ネームスペース付きでrails g modeをすると以下のファイルが作成されます。
①マイグレートファイル
class CreateProjectUsers < ActiveRecord::Migration[7.0] def change create_table :project_users do |t| t.string :email t.timestamps end end end
②self.table_name_prefix
をオーバーライドしてくれるmodule
module Project def self.table_name_prefix "project_" end end
③Projectのネームスペース付きUserモデル
class Project::User < ApplicationRecord end
通常rails g model
する時との違いとして以下があります。
- ① table名にプレフィックスが付与される(
project_users
) - ② self.table_name_prefixをオーバーライドするmoduleが作成される
Project::User
からfindやwhereをした際に、project_xxxx
のテーブルを参照するようになる
- ③ モデル名に
Project::
のようなネームスペースが付与される
既存のプロジェクトをネームスペースに分けたい時
既存のプロジェクトをネームスペースで分けたいけど、テーブル名は変えたくありませんでした。
その際は前述のapp/models/project.rb
にあたるself.table_name_prefix
をオーバーライドするファイルを作成せず、③のようにネームスペース(Project::
)をつけてあげるだけで問題ありませんでした。
Project::User.find
すると発行されるSQLで参照されるテーブル名はusers
のままです。
また、controller等でUser.find
みたいに呼び出している箇所はProject::User.find
のように呼び出すよう修正してみてください。
【puma-dev】 使い方・躓いたこと
初めに
puma-devを使ってみたので、使い方や躓きを簡単にまとめてみました。
概要
pumaとpuma-devに関してさらっと振り返り。
puma
Ruby on RailsのWebアプリケーションに使用されるWebサーバー。
スレッドベースのアーキテクチャを使用し、複数のリクエストを同時に処理する能力を提供している。
スレッドベースのアーキテクチャとは、複数のスレッド(処理の最小単位)を使用して並行処理を実現する方法。
puma-dev
pumaで起動したサーバの一元管理を提供してくれる。
アクセスを受け付けると自動でpumaサーバを立ち上げ、一定時間アクセスがないとスリープにするなど、常にサーバが立ち上がっているような感覚で利用することが可能になる。
使い方
Homebrewでインストール
macを使用しているため、Homebrewからpuma-devをインストールします。
$ brew install puma/puma/puma-dev
DNS設定
puma-devを使うための設定を行います。
sudo puma-dev -setup
セットアップ
これでアプリ名.test
のURLでサーバーにアクセスできます。
puma-dev -install -d test
シンボリックリンクを貼る
puma-devを使用したいプロジェクト配下でシンボリックリンクを貼る
cd sandbox puma-dev link -n sandbox
~/.puma-dev
を確認したら、きちんとシンボリックリンクが設定されているのが確認できます。
早速、http://sandbox.test/ にアクセス。
ホストの設定をしてくれと。
ホストを設定
言われた通りにdevelopment.rb
に設定
config.hosts << "sandbox.test"
躓いた
development.rb
を触ったから、いつも通りrails s
で再起動しようかと思ったら、、あれ?
rails s
再起動
Readmeをきちんと確認したらありました。再起動。
puma-dev で特定のアプリを再起動したい場合は、そのアプリのディレクトリで
touch tmp/restart.txt
実行できます。(翻訳後)
touch tmp/restart.txt
http://sandbox.test/ にアクセス。初期画面表示されました。
最後に
他にpuma-dev と asset に関して躓いたことがあるため別でまとめたいと思います。
【Rails】deviseのメール認証を使えるようにする(Confirmable)・ローカル編
初めに
業務でdeviseのメール認証(Confirmable)を使っていますが、自分でメール認証の設定をしたことがないためアウトプットします。
今回はローカルで動かすところまでやってみます。
ローカルのメール確認にはletter_openerを使用。
手順
deviseのインストール
gem 'devise' group :development do # letter_openerも入れておきます gem 'letter_opener' end
bundle install
# deviseのインストール
rails g devise install
devise日本語化
config/locales/devise.ja.yml
に翻訳ファイルを配置しておきます。
curl -s https://raw.githubusercontent.com/tigrish/devise-i18n/master/rails/locales/ja.yml -o config/locales/devise.ja.yml
メール認証の設定
Userモデル作成
rails g devise user
confirmabaleカラムの有効化
Userモデルを作成時に自動生成されたマイグレーションファイルのConfirmableの箇所のコメントアウトを外す。
# frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[7.0] def change create_table :users do |t| ## Database authenticatable t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" # (省略) ## Confirmable t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email # Only if using reconfirmable # (省略) end end
# マイグレートします
rails db:migrate
モデルの設定変更
:confirmable
を追記
# confirmableを追記 class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :confirmable end
# メールの送信元を設定 config.mailer_sender = 'makky@example.com'
Mailerの設定
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.delivery_method = :letter_opener
flashの設定
deviseから提供されるフラッシュメッセージを表示するようにしておきましょう。
cssにbootstrap使っています。(ここではbootstrapの導入は説明しません。)
- flash.each do |type, message| = content_tag(:div, message, class: "alert alert-#{type == 'notice' ? 'success' : 'danger'}")
動作確認
ユーザー一覧には最初何もなし
http://localhost:3000/users/sign_up にてサインアップ
サインアップ後、メールが送信される
画面にはフラッシュメッセージが表示
本人確認が完了していない状態(メールのリンクを踏んでいない状態)でログインしてみる
本人確認が必要とフラッシュメッセージが表示
メールのリンクから遷移すると、メールアドレスの確認が完了する
ログインが問題なくできるようになる
終わりに
今回はローカルでdeviseのメール認証を使えるようにしてみました。
次は本番環境でどう使うのかアウトプットしてみようと思います。
また、メールアドレスのみでサインアップをし、メールのリンクを踏んだらパスワード入力→そのままログインもやってみたいと思います。
may have been in progress in another thread when fork() was called・rails consoleが中断してしまう
単純にrails consoleからUser.find(...)
的なことをしようとしたら以下のエラーが発生してコンソールが中断してしまうことがありました。
rails c > User.find(...) [__NSCFConstantString initialize] may have been in progress in another thread when fork() was called
こちら(https://github.com/rails/rails/issues/38560)のissueを確認して、解決しました。
解決法
MacOSで発生するエラーみたいですね。 環境変数の設定とspring stopすると一旦は解決しました。
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
spring stop
OBJC_DISABLE_INITIALIZE_FORK_SAFETY
はmacOSで使用される環境変数みたいです。
詳しいことが分かっていないので、調べた後に加筆したいと思います。
【Rails】deviseのモジュールをサラッと確認
deviseモジュール全部みたときに、全部説明しろって言われてたらできないなぁとふと思ったので、とりあえずサラッと確認してみました。
まず導入
rails newは済んでいます。
gem 'devise'
$ bundle $ rails generate devise:install $ rails generate devise User $ rails db:migrate
するとUserモデルはこんな感じになっています。
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable end
それぞれ何ができるのか
database_authenticatable
サインイン時にパスワードをハッシュし、ユーザーの信頼性を検証するためのモジュール。
registerable
新しいリソースの登録(ユーザーのサインアップなど)に関連するモジュール
recoverable
パスワードのリセットを処理するためのモジュール
rememberable
保存されたCookieからユーザーを記憶するためのトークンの生成とクリアを管理するためのモジュール
validatable
ユーザーのメールアドレスとパスワードに必要なすべての検証を作成するためのモジュール パスワードの有無、確認、長さもテストする。
confirmable
メールに記載されているURLから本登録を完了する機能を提供するモジュール。 サインイン中にアカウントが認証済みかどうかも検証できる。
lockable
一定回数の試行後にユーザーアクセスをブロックする処理を行うためのモジュール。ロックを解除するために、解除のためのメールと時間経過の2つの方法を設定できる。
timeoutable
ユーザーセッションがすでに期限切れになっているかどうかを確認するモジュール。 設定された時間後にセッションの有効期限が切れると、ユーザーは再度クレデンシャルを要求され、サインインページにリダイレクトされる。
trackable
ユーザーのサインインに関する情報を追跡するモジュール。 以下のカラムを追跡する。
- sign_in_count: サインインの回数
- current_sign_in_at: サインインののタイムスタンプ
- last_sign_in_at: 前回のサインインのタイムスタンプ
- current_sign_in_ip: ユーザーがサインインした際に更新されるリモート ip。
- last_sign_in_ip: 前回サインインした際のリモート ip を保持する
omniauthable
モデルにOmniAuthサポートを追加するモジュール。
所感
lockable, timeoutable, trackable は何ができるのかちゃんと読んでなかったなぁと反省。 次はdevise導入後に基本的にできることをまとめてみたいと思います。