記述追加 Gemfile (60行目)
gem 'toastr-rails', '~> 1.0' gem 'rails-i18n'
Gemfile
source 'https://rubygems.org' git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.7', '>= 5.0.7.1' # Use postgresql as the database for Active Record gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 3.0' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 3.0' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platform: :mri end group :development do # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. gem 'web-console', '>= 3.3.0' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] #bootstrap gem 'bootstrap-sass', '~> 3.4.1' #デバイス gem 'devise', '~>4.2' #Gravatar gem 'gravtastic' #フラッシュメッセージ gem 'toastr-rails', '~> 1.0' #日本語化 gem 'rails-i18n'
コマンド
bundle
記述追加 app\assets\javascripts\application.js (16行目)
//= require toastr
app\assets\javascripts\application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery //= require bootstrap-sprockets //= require jquery_ujs //= require toastr //= require gravtastic //= require turbolinks //= require_tree .
記述追加 app\assets\stylesheets\application.scss(21行目)
@import "toastr";
app\assets\stylesheets\application.scss
/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require_tree . *= require_self */ //bootstrap @import "bootstrap-sprockets"; @import "bootstrap"; //フラッシュメッセージ @import "toastr"; //基本の設定 body { color: #565a5c; background-color: #F8F8F8; font-family: "Varela Round", "Helvetica Neue", "Helvetica", "Arial", sans-serif; } a { color: #00A699; } .container { width: 80%; } .text-babu, .icon-babu { color: #00A699; } .text-red, .icon-red { color: #FF5A5F; } // ナビゲーションバー .navbar-default { background-color: #FFFFFF; } .navbar-default .navbar-brand { color: #FF5A5F; font-size: 2em; font-weight: 400; } // ボタン .btn-block { display: block; white-space: normal; width: 100%; } .btn { color: #fff; border-radius: 5px; font-weight: bold; padding: 9px 27px; } .btn-small { padding: 5px 15px; margin-top: 15px; } .btn:hover, .btn:focus { color: #fff; } .btn.btn-default { width: 100%; border-color: #c4c4c4; background: white; color: #484848; border-radius: 2px; padding: 10px 0; margin-top: 10px; } .btn.btn-normal { border: 1px solid #ff5a5f; background-color: #ff5a5f; } .btn.btn-normal:active { outline: none; border-color: #e00007; background-color: #e00007; } .btn.btn-form { border: 1px solid #00A699; background-color: #00A699; } .btn.btn-form:active { outline: none; border-color: #066165; background-color: #066165; } .btn.btn-facebook { border: 1px solid #3B5998; background-color: #3B5998; } .btn.btn-facebook:active { outline: none; border-color: #2d467b; background-color: #2d467b; } // パネル .panel-default .panel-heading { color: #ffffff; background-color: #00A699; font-size: 18px; font-weight: 400; } .row-space-1 { margin-top: 6px; margin-bottom: 6px; } .row-space-2 { margin-top: 12px; margin-bottom: 12px; } .row-space-3 { margin-top: 24px; margin-bottom: 24px; } .description { color: #575757; font-size: 15px; font-weight: 500; line-height: 25px; } // アバター .avatar-small { width: 28px; } .avatar-medium { width: 48px; } .avatar-large { width: 68px; } .avatar-full { width: 100%; } // フォーム .form-group { margin-bottom: 25px; } .form-control { border-radius: 2px; height: 4rem; } .form-group input { height: 45px; border: 1px solid #00A699; } .form-group textarea { border: 1px solid #00A699; } .form-group input[type="radio"] { height: 15px; margin-right: 10px; } .btn-group label { margin-right: 15px; } .form-group select { width: 100%; color: #565a5c; background-color: white; border: 1px solid #00A699; border-radius: 2px; padding: 10px; appearance: none; -moz-appearance: none; /* Firefox */ -webkit-appearance: none; /* Safari & Chrome */ } .select:before { content: '\25bc'; font-size: 1.2em; position: absolute; color: #00A699; top: 35px; right: 30px; transform: scale(0.94, 0.62); } .form-group input[type="checkbox"] { height: 1.25em; width: 1.25em; margin-bottom: -0.25em; margin-right: 5px; vertical-align: top; border: 1px solid #00A699; border-radius: 2px; appearance: none; -moz-appearance: none; -webkit-appearance: none; } .form-group input[type="checkbox"]:checked:before { content: '\2713'; position: absolute; font-size: 0.95em; text-align: center; width: 1.25em; color: #00A699; } // スライダー .sidebar-list { padding-left: 0; list-style: none; } .sidebar-item { padding: 10px 0; font-size: 16px; color: #82888a; } .sidebar-link { color: #82888a; text-decoration: none; } .sidebar-link:hover, .sidebar-link:focus { color: #CACCCD; text-decoration: none; } .active.sidebar-link { color: #565A5C; font-weight: bold; text-decoration: none; } // 画像アップロード .btn-file { position: relative; overflow: hidden; } .btn-file input[type=file] { position: absolute; top: 0; right: 0; min-width: 100%; min-height: 100%; font-size: 100px; text-align: right; filter: alpha(opacity=0); opacity: 0; outline: none; background: white; cursor: inherit; display: block; } .panel-heading.preview { padding: 0; } .panel-heading.preview img { width: 100%; } // 部屋の表示 .amenities li { margin-bottom: 10px; font-size: 16px; list-style-type: none; } .amenities .text-line-through { text-decoration: line-through; color: rgba(0,0,0,0.45); font-size: 14px; } // 予約 .reservation-table td { width: 100%; border: none; border-bottom: 1px solid #dce0e0; padding: 10px; } .reservation-table .total td { font-size: 16px; font-weight: bold; border: none; } .form-control.datepicker { color: #00A699; background-color: white; border: 1px solid #00A699; text-align: center; } .message-alert { color: #d43242; font-size: 14px; padding-top: 10px; } // 検索 #main { height: 100%; overflow: hidden; } #left { padding: 10px 400px 10px 20px; overflow: scroll; height: 100%; } #right { position: fixed; top: 0; right: 0; width: 450px; height: 100%; } .map_price { text-align: center; font-size: 16px; font-weight: 600; color: #00A699; } // ホームページ .discovery-card { background-size: cover; background-position: center; height: 326px; } .banner { margin-top: 50px; margin-bottom: 50px; } // カレンダー .fc-content.Waiting { background-color: #C9CC6D; } .fc-past { background-color: lightgray; } .fc-day { position: relative; } .fc-content { background-color: #00A699; height: 40px; border-radius: 20px; } .fc-event { border: 0px; background-color: transparent; } .fc-title { font-size: 14px; position: relative; top: 7px; left: 20px; } .day-price { position: absolute; color: #EAA90B; bottom: 2px; right: 2px; } .badge { background-color: #FF5A5F; position: relative; top: -15px; left: -5px; } #add-card form { width: 480px; margin: 20px auto; } #add-card label { position: relative; color: #6A7C94; font-weight: 400; height: 48px; line-height: 48px; margin-bottom: 10px; display: block; } #add-card label > span { float: left; } .field { background: white; box-sizing: border-box; font-weight: 400; border: 1px solid #CFD7DF; border-radius: 24px; color: #32315E; outline: none; height: 48px; line-height: 48px; padding: 0 20px; cursor: text; width: 76%; float: right; } .field::-webkit-input-placeholder { color: #CFD7DF; } .field::-moz-placeholder { color: #CFD7DF; } .field:-ms-input-placeholder { color: #CFD7DF; } .field:focus, .field.StripeElement--focus { border-color: #F99A52; } #add-card button { float: left; display: block; background-image: linear-gradient(-180deg, #F8B563 0%, #F99A52 100%); box-shadow: 0 1px 2px 0 rgba(0,0,0,0.10), inset 0 -1px 0 0 #E57C45; color: white; border-radius: 24px; border: 0; margin-top: 20px; font-size: 17px; font-weight: 500; width: 100%; height: 48px; line-height: 48px; outline: none; } #add-card button:focus { background: #EF8C41; } #add-card button:active { background: #E17422; } .outcome { float: left; width: 100%; padding-top: 8px; min-height: 20px; text-align: center; } .success, .error { display: none; font-size: 13px; } .success.visible, .error.visible { display: inline; } .error { color: #E4584C; }
「app\views\shared」フォルダに「_message.html.erb」ファイルを新規作成
app\views\shared\_message.html.erb (新規作成したファイル)
<% unless flash.empty? %> <script type="text/javascript"> <% flash.each do |key, value| %> <% type = key.to_s.gsub('alert','error').gsub('notice','success') %> toastr['<%= type %>']('<%= value %>') <% end %> </script> <% end %>
「app\views\layouts\application.html.erb」ファイルを編集します。
記述削除 app\views\layouts\application.html.erb(17行目)
<p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p>
記述追加 app\views\layouts\application.html.erb(15行目)
<%= render 'shared/message' %>
app\views\layouts\application.html.erb
<!DOCTYPE html> <html> <head> <title>Minpaku</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <!-- _navbar.html.erb をレンダーする --> <%= render 'shared/navbar' %> <%= render 'shared/message' %> <!-- ページをコンテナに格納 --> <div class="container"> <%= yield %> </div> </body> </html>
メッセージの日本語化設定をします。
「config\locales」フォルダに「devise.ja.yml」ファイルを新規作成します。
config\locales\devise.ja.yml(新規作成したファイル)
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n ja: devise: confirmations: confirmed: 'アカウントを登録しました。' send_instructions: 'アカウントの有効化について数分以内にメールでご連絡します。' send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、本人確認用のメールが数分以内に送信されます。" failure: already_authenticated: 'すでにログインしています。' inactive: 'アカウントが有効化されていません。メールに記載された手順にしたがって、アカウントを有効化してください。' invalid: "%{authentication_keys} もしくはパスワードが不正です。" locked: 'あなたのアカウントは凍結されています。' last_attempt: 'あなたのアカウントが凍結される前に、複数回の操作がおこなわれています。' not_found_in_database: "%{authentication_keys} もしくはパスワードが不正です。" timeout: 'セッションがタイムアウトしました。もう一度ログインしてください。' unauthenticated: 'アカウント登録もしくはログインしてください。' unconfirmed: 'メールアドレスの本人確認が必要です。' mailer: confirmation_instructions: subject: 'アカウントの有効化について' reset_password_instructions: subject: 'パスワードの再設定について' unlock_instructions: subject: 'アカウントの凍結解除について' password_change: subject: 'パスワードの変更について' omniauth_callbacks: failure: "%{kind} アカウントによる認証に失敗しました。理由:(%{reason})" success: "%{kind} アカウントによる認証に成功しました。" passwords: no_token: "このページにはアクセスできません。パスワード再設定メールのリンクからアクセスされた場合には、URL をご確認ください。" send_instructions: 'パスワードの再設定について数分以内にメールでご連絡いたします。' send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、パスワード再設定用のメールが数分以内に送信されます。" updated: 'パスワードが正しく変更されました。' updated_not_active: 'パスワードが正しく変更されました。' registrations: destroyed: 'アカウントを削除しました。またのご利用をお待ちしております。' signed_up: 'アカウント登録が完了しました。' signed_up_but_inactive: 'ログインするためには、アカウントを有効化してください。' signed_up_but_locked: 'アカウントが凍結されているためログインできません。' signed_up_but_unconfirmed: '本人確認用のメールを送信しました。メール内のリンクからアカウントを有効化させてください。' update_needs_confirmation: 'アカウント情報を変更しました。変更されたメールアドレスの本人確認のため、本人確認用メールより確認処理をおこなってください。' updated: 'アカウント情報を変更しました。' sessions: signed_in: 'ログインしました。' signed_out: 'ログアウトしました。' already_signed_out: '既にログアウト済みです。' unlocks: send_instructions: 'アカウントの凍結解除方法を数分以内にメールでご連絡します。' send_paranoid_instructions: 'アカウントが見つかった場合、アカウントの凍結解除方法を数分以内にメールでご連絡します。' unlocked: 'アカウントを凍結解除しました。' errors: messages: already_confirmed: 'は既に登録済みです。ログインしてください。' confirmation_period_expired: "の期限が切れました。%{period} までに確認する必要があります。 新しくリクエストしてください。" expired: 'の有効期限が切れました。新しくリクエストしてください。' not_found: 'は見つかりませんでした。' not_locked: 'は凍結されていません。' not_saved: one: "エラーが発生したため %{resource} は保存されませんでした:" other: "%{count} 件のエラーが発生したため %{resource} は保存されませんでした:"
同じく「config\locales」フォルダに「ja.yml」ファイルを新規作成
config\locales\ja.yml(新規作成したファイル)
ja: activerecord: attributes: user: fullname: 氏名 current_password: パスワード password: パスワード email: メールアドレス time: formats: full_date: "%Y年%m月%d日 (%a)"
記述追加 config\application.rb(15行目)
#日本語化 config.i18n.default_locale = :ja # 日本時間に変更 config.time_zone = 'Tokyo'
config\application.rb
require_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Minpaku class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. #日本語化 config.i18n.default_locale = :ja # 日本時間に変更 config.time_zone = 'Tokyo' end end
「views\shared」フォルダに「_devisemes.html.erb」ファイルを新規作成
app\views\shared\_devisemes.html.erb(新規作成したファイル)
<% unless resource.errors.empty? %> <script type="text/javascript"> <% resource.errors.full_messages.each do |value| %> toastr.error('<%= value %>') <% end %> </script> <% end %>
以下の4つのファイルに記述の削除と記述追加。
- app\views\devise\registrations\new.html.erb
- app\views\devise\registrations\edit.html.erb
- app\views\devise\passwords\new.html.erb
- app\views\devise\passwords\edit.html.erb
削除する記述
<%= render "devise/shared/error_messages", resource: resource %>
追加する記述
<%= render 'shared/devisemes' %>
1. app\views\devise\registrations\new.html.erb(9行目)
<div class="row"> <div class="col-md-4 col-md-offset-4"> <h2 class="text-center">新規ユーザ登録</h2> <br/> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= render 'shared/devisemes' %> <div class="form-group"> <%= f.text_field :fullname, autofocus: true, placeholder: "氏名", class: "form-control" %> </div> <div class="form-group"> <%= f.email_field :email, autofocus: true, placeholder: "メールアドレス", class: "form-control" %> </div> <div class="form-group"> <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %> </div> <div class="actions"> <%= f.submit "登録", class: "btn btn-normal btn-block" %> </div> <% end %> </div> </div>
2. app\views\devise\registrations\edit.html.erb(9行目)
<div class="row"> <div class="col-md-4 col-md-offset-4"> <h2 class="text-center">ユーザ登録情報の編集</h2> <br/> <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> <%= render 'shared/devisemes' %> <div class="form-group"> <%= f.text_field :fullname, autofocus: true, placeholder: "氏名", class: "form-control" %> </div> <div class="form-group"> <%= f.email_field :email, autofocus: true, placeholder: "メールアドレス", class: "form-control" %> </div> <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> <div>現在、次の確認を待っています:<%= resource.unconfirmed_email %></div> <% end %> <div class="form-group"> <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード(変更しない場合は空白のまま)", class: "form-control" %> <div class="form-group"> <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "確認(変更しない場合は空白のまま)", class: "form-control" %> </div> <div class="form-group"> <%= f.password_field :current_password, autocomplete: "off", placeholder: "現在のパスワード", class: "form-control" %> </div> <div class="actions"> <%= f.submit "更新する", class: "btn btn-normal btn-block" %> </div> <% end %> </div> </div>
3. app\views\devise\passwords\new.html.erb(8行目)
<div class="row"> <div class="col-md-4 col-md-offset-4"> <h2 class="text-center">パスワードをお忘れの方</h2> <br/> <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> <%= render 'shared/devisemes' %> <div class="form-group"> <%= f.email_field :email, autofocus: true, autocomplete: "メールアドレス", placeholder: "メールアドレス", class: "form-control" %> </div> <br/> <div class="actions"> <%= f.submit "パスワードのリセット申請を送る", class: "btn btn-primary" %> </div> <% end %> </div> </div>
4. app\views\devise\passwords\edit.html.erb(8行目)
<div class="row"> <div class="col-md-4 col-md-offset-4"> <h2>新しいパスワードに変更</h2> <br/> <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> <%= render 'shared/devisemes' %> <%= f.hidden_field :reset_password_token %> <div class="form-group"> <%= f.password_field :password, autocomplete: "off", placeholder: "新しいパスワード", class: "form-control" %> </div> <div class="form-group"> <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "確認", class: "form-control" %> </div> <br/> <div class="actions"> <%= f.submit "パスワードを変更する", class: "btn btn-primary" %> </div> <% end %> </div> </div>
ブラウザ確認
http://localhost:3000/