Deviseの日本語化やBootstrap4の導入方法の記事はよく見かけます。ところが……
- ビューファイルを作成するときに,結局どのコマンドを使えばよいか分からない
rails g devise:views
rails g devise:i18n:views
rails g devise:views:bootstrap_templates
- 全て導入したはずなのにメール文が日本語化されない
など,順序を間違えると問題が発生します。そこで,ログイン画面を最低限のスタイルで実装するところまでをまとめてみました。
開発環境
- macOS Catalina 10.15.7
- Ruby 2.7.2
- Rails 6.0.3.4 (Rails 5 にも対応)
- Bootstrap 4.5.0
- Devise 4.7.1 (confirmableなどの導入過程は記載していません)
YouTube
- YouTubeに解説動画をアップしました
【注意】 2019年11月時点の録画ですので,現在の記事の構成と変更されている部分が多々あります
0. 準備
- 以下の前提で進めていきます。
- データベースを PostgreSQL に指定するオプション
-d postgresql
はお好みです - トップページは
homes#index
の前提で進めます -
Rails 5
でアプリを作成する場合は,rails new
をrails _5.2.4.4_ new
のような書き方で指定して下さい
- データベースを PostgreSQL に指定するオプション
rails new devise_sample -d postgresql
cd devise_sample
rails g controller homes index
touch app/views/layouts/_flash_messages.html.erb app/views/layouts/_header.html.erb
Rails.application.routes.draw do
root 'homes#index'
end
- ナビバーを追加し,レスポンシブ対応のためのmetaタグを追加
(略)
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
+ <meta name="viewport" content="width=device-width,initial-scale=1">
(略)
<body>
+ <%= render 'layouts/header' %>
<%= yield %>
</body>
<%= render 'layouts/flash_messages' %>
<% flash.each do |msg_type, msg| %>
<div class="alert alert-<%= msg_type %>" role="alert" id="alert">
<a href="#" class="close" data-dismiss="alert">×</a>
<%= msg %>
</div>
<% end %>
<header>
<nav class="navbar navbar-expand navbar-light">
<%= link_to "Deviseサンプル", root_path, class: 'navbar-brand' %>
<div id="Navber">
<ul class="navbar-nav">
<% if user_signed_in? %>
<li class="nav-item active">
<%= link_to 'アカウント編集', edit_user_registration_path, class: 'nav-link' %>
</li>
<li class="nav-item active">
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete, class: 'nav-link' %>
</li>
<% else %>
<li class="nav-item active">
<%= link_to "新規登録", new_user_registration_path, class: 'nav-link' %>
</li>
<li class="nav-item active">
<%= link_to "ログイン", new_user_session_path, class: 'nav-link' %>
</li>
<% end %>
</ul>
</div>
</nav>
</header>
/*
*= require_tree .
*= require_self
*/
// max-width
.mw-md {
max-width: 576px;
}
// 「ログインしました」などのフラッシュ用スタイル
.alert-notice {
@extend .alert-info;
}
.alert-alert {
@extend .alert-danger;
}
【注意】 この時点でサーバーを起動してもエラーが出ます。1章完了後にサーバーを起動して動作確認をして下さい。
1. Gemの追加
1.1 Rails 6 の場合
- Gemfileに以下を追加
# ログイン機能
gem 'devise'
# 日本語化
gem 'rails-i18n', '~> 6.0'
gem 'devise-i18n'
# Bootstrap
gem 'devise-bootstrap-views', '~> 1.0'
- ターミナルから次を実行
bundle install
1.2 Rails 5 の場合
- Gemfileに以下を追加
# ログイン機能
gem 'devise'
# 日本語化
gem 'rails-i18n', '~> 5.1'
gem 'devise-i18n'
# Bootstrap
gem 'bootstrap', '~> 4.5'
gem 'jquery-rails'
gem 'devise-bootstrap-views', '~> 1.0'
- ターミナルから次を実行
bundle install
2. Bootstrapの導入
2.1 Rails 6 の場合
【参考】(Stackoverflow) Setup Bootstrap 4.3 on Rails 6 using Webpack
- ターミナルから次を実行
yarn add bootstrap jquery popper.js
-
environment.js
を次に置き換える
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
}))
module.exports = environment
-
application.js
の一番下に次を追加
require("bootstrap/dist/js/bootstrap")
-
application.css
の拡張子css
をscss
に変更 -
@import "bootstrap/scss/bootstrap";
を追加
/*
*= require_tree .
*= require_self
*/
// ***** 次を追加 *****
@import "bootstrap/scss/bootstrap";
// ***** 以上を追加 *****
// max-width
// 略
2.2 Rails 5 の場合
-
application.css
の拡張子をscss
に変更 -
application.scss
から,*= require_tree .
と*= require_self
を削除 -
application.scss
に@import "bootstrap";
を追加
@import "bootstrap";
// max-width
// 略
-
application.js
に3つ追加
//= require jquery3
//= require popper
//= require bootstrap-sprockets
3. Deviseの導入
Devise
をインストール(user
の箇所は,任意のモデル名
でOKです)ターミナルから次を実行
rails g devise:install
rails g devise user
rails db:create db:migrate
- 問題がなければ,
rails s
の後,http://localhost:3000
からログイン
ボタンを押せば,ログイン画面が表示されます。
-
gem 'devise-bootstrap-views'
を追加しているので, Bootstrapもある程度適用されています。- 公式(hisea/devise-bootstrap-views)
- 横幅一杯表示されるのはちょっと……と思われるかもしれませんが,さらに見た目を整える作業は最後にします。
4. Deviseの日本語化
module AssociationTutorial
class Application < Rails::Application
# 以下を追加すれば日本語に
+ config.i18n.default_locale = :ja
# タイムゾーンも変更するなら,以下を追加
+ config.time_zone = 'Asia/Tokyo'
end
end
- サーバーを落として
rails s
で再起動すれば日本語に変更されます。
5. メールを送信できるようにする(Gmailかつ開発環境のみ対応)
-
送信元の表示名
を変更しておきます。- タイトル名はこの設定が反映されますが,メールアドレスの箇所は実際の送信するアドレスになります。
Devise.setup do |config|
- config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
+ config.mailer_sender = 'タイトル名 <noreply@example.com>'
end
Gmailから送信する場合,安全性の低いアプリのアクセスを有効にする必要があります。
-
development.rb
のconfig.action_mailer.raise_delivery_errors = false
の箇所を置き換えます。- メールアドレスやパスワードをgitの管理下に入れるのを避け,
credentials
管理にしておきます。本番環境で無駄にエラーが出ないようダミー情報を入れておきます。
- メールアドレスやパスワードをgitの管理下に入れるのを避け,
# 削除 config.action_mailer.raise_delivery_errors = false
# 以下に置き換え
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
if Rails.application.credentials.gmail.present?
mail_address = Rails.application.credentials.gmail[:address]
password = Rails.application.credentials.gmail[:password]
else
mail_address = 'admin@example.com'
password = 'password'
end
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
enable_starttls_auto: true,
address: "smtp.gmail.com",
port: 587,
user_name: mail_address,
password: password,
authentication: "plain"
}
-
EDITOR=vi rails credentials:edit
で,credentials
の中に,メールアドレスとパスワードを記載します。
gmail:
address: 送信に使用するメールアドレス
password: 送信に使用するパスワード
変更を反映するため,サーバーを落として
rails s
で再起動します。メール送信の確認をするには,あらかじめ新規登録をした上で,ログイン画面の
パスワードを忘れましたか?
をクリックしてパスワード再設定メールを送信すればOKです。
6. 日本語訳を変更
日本語訳を変更したい場合は,次のコマンドでconfig/locales/devise.views.ja.yml
を作成し,編集すればOKです。
rails g devise:i18n:locale ja
例えば
アカウント登録
を新規登録
に変更したい場合は,devise.views.ja.yml
の該当文字を置換すればOKです。パスワードを忘れましたか?
も違和感がありますので,パスワードの再設定
に置換するのがよいと思います。
7. ログイン画面などの変更
- まず,次のコマンドでビューファイルを作成します。
rails g devise:i18n:views
rails g devise:views:bootstrap_templates -f
- 【参考】それぞれのコマンドの最後に例えば
user
をつけることで,users
ディレクトリ内にファイルを作成することもできますが,その場合は,次の3つの作業を行わないと反映されません。-
devise.views.ja.yml
30行目のdevise
をusers
に変更 -
config/initializers/devise.rb
にあるconfig.scoped_views = false
のコメントアウトを外してtrue
に変更 - サーバーを落として
rails s
で再起動
-
【注意】 ここから先はお好みで採用して下さい。
- 全体を中央に寄せたいが無駄に横長になっている状態を改善する場合は
application.html.erb
の<%= yield %>
を次のような<div>
タグで囲みましょう。
<div class="container-fluid py-4 mw-md">
<%= yield %>
</div>
【補足】 例えば, devise
関連のページのみ最大の横幅を 576px として,それ以外は別の横幅にしたい場合は,条件分岐で付与するクラスを付けかえるようにしましょう。
<div class="container-fluid py-4 <%= devise_controller? ? 'mw-md' : 'mw-xl' %>">
<%= yield %>
</div>
// max-width
.mw-md {
max-width: 576px;
}
// ***** 以下を追加 *****
.mw-xl {
max-width: 1200px;
}
devise_controller? ? 'mw-md' : 'mw-xl'
の箇所はヘルパーにメソッドを作成し,呼び出す方が理想的でしょう。
- エラーメッセージの表示がいまいちなので変更するためにオーバーライドします。
module DeviseHelper
def bootstrap_devise_error_messages!
return "" if resource.errors.empty?
html = ""
resource.errors.full_messages.each do |error_message|
html += <<-EOF
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
<span class="sr-only">close</span>
</button>
#{error_message}
</div>
EOF
end
html.html_safe
end
end
- 次のGemは役目を終えているので削除してもOKです。
- gem 'devise-bootstrap-views', '~> 1.0'
bundle install
- ログイン画面だけエラーメッセージが表示されないので,追加しておきます。
<div class="container-login">
<h1><%= t('.sign_in') %></h1>
+ <%= render 'layouts/flash_messages' %>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
-
app/views/devise
ディレクトリ内のファイルのbtn btn-primary
をbtn btn-primary btn-block
に置換すればボタンの横幅が自然になります。
- バリデーションはフロント側にも簡単に入れられます。
-
f.email_field
,f.password_field
にrequired: true
を入れることで空欄投稿できなくなります。 - 新規登録(アカウント登録)画面では,例えば,
f.password_field
にrequired: true, minlength: @minimum_password_length, maxlength: '30'
を追加すれば,文字数のバリデーションを追加できます。
-
<div class="form-group">
<%= f.label :password %>
- <%= f.password_field :password, autocomplete: 'current-password',
- class: 'form-control' %>
+ <%= f.password_field :password, autocomplete: 'current-password',
+ class: 'form-control',
+ required: true,
+ minlength: @minimum_password_length,
+ maxlength: '30' %>
-
_links.html.erb
を編集して,一番下のリンクをボタンにしてみます。
<hr class="border-dark my-5">
<div class="form-group">
<%- if controller_name != 'sessions' %>
<%= link_to t(".sign_in"), new_session_path(resource_name), class: 'btn btn-info btn-block' %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to t(".sign_up"), new_registration_path(resource_name), class: 'btn btn-info btn-block' %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to t(".forgot_your_password"), new_password_path(resource_name), class: 'btn btn-secondary btn-block' %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name), class: 'btn btn-secondary btn-block' %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to t('.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name), class: 'btn btn-secondary btn-block' %><br />
<% end -%>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to t('.sign_in_with_provider', provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider), class: 'btn btn-info btn-block' %><br />
<% end -%>
<% end -%>
</div>
- さらに,リンクの
ログイン
,新規登録(アカウント登録)
を次のように変更してみます。
# 上2つを次に置き換え
<%- if controller_name != 'sessions' %>
<%= link_to "アカウントをお持ちの方", new_session_path(resource_name), class: 'btn btn-info btn-block' %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "アカウントをお持ちでない方", new_registration_path(resource_name), class: 'btn btn-info btn-block' %><br />
<% end -%>
- 最後にアカウント編集機能を修正しておきます。色々中途半端ですね……
- <h1><%= t('.title', resource: resource_name.to_s.humanize) %></h1>
+ <h1>アカウント編集</h1>
(中略)
<!-- ここから -->
<p><%= t('.unhappy') %>
? <%= link_to t('.cancel_my_account'), registration_path(resource_name), data: {confirm: t('.are_you_sure')}, method: :delete %>
.</p>
<%= link_to t('.back'), :back %>
<!-- ここまでを次に置き換える -->
<hr class="devise-link my-5">
<div class="form-group">
<%= link_to "トップページ", root_path, class: 'btn btn-info btn-block mb-4' %>
<%= link_to t('.cancel_my_account'), registration_path(resource_name), data: {confirm: t('.are_you_sure')}, method: :delete, class: 'btn btn-danger btn-block' %>
</div>
単純なスタイルですが,ログイン機能がだいぶ整ったのではないでしょうか。
コメント