#1. はじめに
今回はDeviseを使ってログイン機能を作成していきます。
またDeviseの日本語化やBootstrap4の適用までを行っていきます。
#2. 準備
$ rails new devise-sample
$ rails g controller homes index
Rails.application.routes.draw do
root 'homes#index'
end
#3. ナビバーを追加し,レスポンシブ対応のためのmetaタグを追加
(略)
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<meta name="viewport" content="width=device-width,initial-scale=1"> //追加
(略)
<body>
<%= render 'shared/header' %> //追加
<%= yield %>
</body>
新しくsharedフォルダと各renderファイルを作成
フラッシュメッセージ
エラーメッセージを呼び出す。
<% 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 %>
<%= render 'shared/flash_messages' %>
####ヘッダー
<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>
#4. Gemの追加
Gemfileに以下を追加して$ bundle install
# ログイン機能に必要なGem
gem 'devise'
# 日本語化に必要なGem
gem 'rails-i18n', '~> 5.1'
gem 'devise-i18n'
# Bootstrapに必要なGem
gem 'bootstrap', '~> 4.4.1'
gem 'jquery-rails'
gem 'devise-bootstrap-views', '~> 1.0'
$ bundle install
##Bootstrapの導入
-
application.css
の拡張子をscss
に変更 -
application.scss
から,*= require_tree .
と*= require_self
を削除 -
application.scss
に@import "bootstrap";
を追加 -
スタイルも追加
@import "bootstrap";
// ログイン画面
.container-login {
@extend .container-fluid;
max-width: 576px;
padding: 2rem;
}
// 「ログインしました」などのフラッシュ用スタイル
.alert-notice {
@extend .alert-info;
}
.alert-alert {
@extend .alert-danger;
}
###application.jsに3つ追加
Bootstrapと依存関係をapplication.jsに追記する
//= require jquery3
//= require popper
//= require bootstrap-sprockets
補足
- Bootstrapのtooltipsやpopoverはpopper.jsに依存している
- bootstrapの依存gemにpopper_jsが指定されているため新たにインストールは不要
- コンパイルを高速化したい場合はbootstrap-sprocketsの代わりにbootstrapを指定する
##Deviseの導入
Devise
をインストール(userの箇所は,任意のモデル名でOKです)
$ rails g devise:install
$ rails g devise user
$ rails db:create db:migrate
問題がなければ,$ rails s
の後,http://localhost:3000
からログインボタンを押せば,ログイン画面が表示されます。
##Deviseの日本語化
module AssociationTutorial
class Application < Rails::Application
# 以下を追加すれば日本語に
config.i18n.default_locale = :ja
# タイムゾーンも変更するなら,以下を追加
config.time_zone = 'Asia/Tokyo'
end
end
サーバーを落として$ rails s
で再起動すれば日本語に変更されます。
日本語訳を変更
日本語訳を変更したい場合は,次のコマンドでconfig/locales/devise.views.ja.yml
を作成し,編集すればOKです。
$ rails g devise:i18n:locale ja
例えばアカウント登録を新規登録に変更したい場合は,config/locals/devise.views.ja.yml
の該当文字を置換すればOKです。
パスワードを忘れましたか?も違和感がありますので,パスワードの再設定に置換するのがよいと思います
##ログイン画面などの変更
まず,次のコマンドでビューファイルを作成します。
$ 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
で再起動
お好みで変えていく
例えば
<div class="container-login">
# 元のプログラム
</div>
##エラーメッセージの変更
エラーメッセージの表示がいまいちなので変更するためにオーバーライドします。
app/helpers/devise_helper.rb
ファイルを作成し、以下を記述。
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
###ログイン画面にもエラーメッセージを追加
<div class="container-login">
<h1><%= t('.sign_in') %></h1>
<%= render 'shared/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 -%>
<!-- ここから -->
<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>
これで一応単純なスタイルは完成です。
もし間違っているところがあればご教授いただけると幸いです。