step の追加
Gemfile に capybara-webkit が入っていませんでした。
gem 'capybara-webkit'
を追加しておきました。
それでは、steps を保存するフォルダを作成します。
mkdir -p spec/acceptance/steps
このフォルダを rspec 時に読み込むように spec_helper.rb に設定します。
Dir.glob("spec/acceptance/steps/*steps.rb") { |f| load f, true }
このフォルダ内に top_page_steps.rb を追加します。
# encoding: utf-8 step 'トップページを表示する' do visit '/' end step '画面に森高千里データベースと表示されていること' do expect(page).to have_content('森高千里データベース') end
Rspec 内での実行となるので、テスト表記は except().to で記載できます。 このファイルを保存したと同時に Guard によりテストが動作します。
07:25:12 - INFO - Running: spec/acceptance/top_page.feature 日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること (FAILED - 1) Failures: 1) 日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること Failure/Error: ならば 画面に森高千里データベースと表示されていること ActionController::RoutingError: No route matches [GET] "/" # spec/acceptance/steps/top_page_steps.rb:4:in `block in <top (required)>' # ./spec/acceptance/top_page.feature:6:in `block (6 levels) in run' # ./spec/acceptance/top_page.feature:5:in `each' # ./spec/acceptance/top_page.feature:5:in `block (5 levels) in run' # -e:1:in `<main>' # ./spec/acceptance/top_page.feature:5:in `トップページを表示する' Finished in 0.01046 seconds 1 example, 1 failure Failed examples: rspec ./spec/acceptance/top_page.feature:4 # 日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること
Jenkins のエラーの確認
テストがエラーになったので、Jenkins でエラーが確認できるかどうかをチェックしてみます。steps をリポジトリにコミットすれば、Jenkins が起動してエラーになるはずです。今回、Gemfile を修正したため、bundle のやり直しがありテストに時間がかかりますが、正しく失敗ビルドとなっていることがわかります。
日本語トップページの表示
日本語のトップページを表示するために config/routes.rb に routing 情報を追加します。
root 'top#index'
このファイルを更新しても Guard テストは実行されないので、guard の画面でリターンキーを叩くとテストが手動起動します。もしくは、以前書いた feature もしくは steps を更新しても Ok です。
1) 日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること Failure/Error: ならば 画面に森高千里データベースと表示されていること ActionController::RoutingError: uninitialized constant TopController
エラーが代わり、TopController がないというエラーに変わっていることがわかります。generator で top_controller.rb を作成します。
r g controller top
コントローラ、ビューのテストは作成しないことにしていたので、作成されるのは
- app/controllers/top_controller.rb
- app/views/top
だけになります。この結果、エラーが以下のように変化します。
Failure/Error: ならば 画面に森高千里データベースと表示されていること AbstractController::ActionNotFound: The action 'index' could not be found for TopController
次に app/controllers/top_controller.rb に index メソッドを追加します。
def index end
Guard の結果は以下のように変化します。
Failure/Error: ならば 画面に森高千里データベースと表示されていること ActionView::MissingTemplate: Missing template top/index, application/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee, :haml]}. Searched in: * "/Users/hkob/rails/moritaka-db/app/views" * "/Users/hkob/rails/moritaka-db/vendor/bundle/ruby/2.1.0/gems/kaminari-0.15.1/app/views"
index がないと言われるので、app/views/top/index.html.haml を作成します。国際化対応にするため、t メソッドで locales からメッセージを選択するようにします。
%h1=t '.title'
ページを確認すると、ローカライズできていないので、画面には Title としか表示されません。当然ながらテストも通りません。
日本語・英語版の切替を実現する 日本語のトップページにアクセスする [deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message. トップページを表示する -> 画面に森高千里データベースと表示されていること (FAILED - 1) Failures: 1) 日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること Failure/Error: ならば 画面に森高千里データベースと表示されていること expected to find text "森高千里データベース" in "Title" # spec/acceptance/steps/top_page_steps.rb:8:in `block in <top (required)>' # ./spec/acceptance/top_page.feature:6:in `block (6 levels) in run' # ./spec/acceptance/top_page.feature:5:in `each' # ./spec/acceptance/top_page.feature:5:in `block (5 levels) in run' # -e:1:in `<main>' # ./spec/acceptance/top_page.feature:6:in `画面に森高千里データベースと表示されていること'
I18n.enforce_available_locales が将来的に true にセットされるので、validation したくなければ false にセットしておくように警告が出ています。メッセージが出てくるのが面倒なので、config/application.rb に設定しておくことにします。また、ほとんどの人が日本語版を見ると思うので、default_locale は :ja にセットしておきます。
I18n.enforce_available_locales = true config.i18n.default_locale = :ja
さらに、すべてのコントローラで locale を設定するために、app/controllers/application_controller.rb にて before_action を設定します。
before_action :set_locale AVAILABLE_LOCALES = %w(en ja) def set_locale I18n.locale = params[:locale] || I18n.default_locale @is_ja = I18n.locale == :ja end
さらに、すべてのリンクに locale オプションが設定されるように default_url_options を設定します。
def default_url_options(options = {}) { locale:I18n.locale } end
次に locales データを準備します。views の locales データを保存するために、config/locales/views を作成しておきます。
mkdir -p config/locales/views
config/locales/views/ja.yml を記載します。haml において、「.title」と階層を省略したため、locales データは views と同じ階層にしておく必要があります(Rails 3 の I18n についてを参照)。
ja: top: index: title: "森高千里データベース"
この状態で Guard を見るとテストが無事に成功していることがわかります。せっかくなので、コミットして Jenkins でも確認しておきます。
英語版へのリンク
すべてのページに日本語版・英語版への相互リンクを作成します。ページのトップに各メニューへのリンクを載せると共に、相互リンクを掲載することにします。まず、テスト(spec/acceptance/top_page.feature)を修正・追加します。
# encoding: utf-8 # language: ja 機能: 日本語・英語版の切替を実現する シナリオ: 日本語のトップページにアクセスする 前提 トップページを表示する ならば 画面に "森高千里データベース" と表示されていること シナリオ: 英語のトップページに切り替える 前提 トップページを表示する もし "[English]" をクリックする ならば 画面に "Chisato Moritaka Database" と表示されていること シナリオ: 再度日本語のトップページに切り替える 前提 トップページを表示する もし "[English]" をクリックする かつ "[Japanese]" をクリックする ならば 画面に "森高千里データベース" と表示されていること
表示する文字列ごとに step を書くのは莫迦らしいので、文字列の部分を変数で指定できるようにします。同様にクリックするリンク名も変数で設定できるようにします。修正後の spec/acceptance/steps/top_page_steps.rb は以下のようになります。
step '画面に :string と表示されていること' do |string| expect(page).to have_content(string) end step ":link をクリックする" do |name| click_link name end
すべてのページにリンクバーを掲載するため、app/views/layouts/application.html.haml に partial で読み込みます。
%body =render partial:'shared/top_link_bar', locals:{ navi:@navi } = yield
shared フォルダを作成します。
mkdir -p app/views/shared
app/views/shared/_top_link_bar.html.haml にリンクバーを作成します。体裁はあとあと css で何とかするので、今はとりあえず table でリンクを並べることにします。日本語・英語の相互リンクは recursive_path というメソッドで locale のみを入れ換えることで可能となります。
%table %tr %td=link_to lh(t 'link.home'), root_path %td -if @is_ja =link_to lh(:English), recursive_path(locale: :en) -else =link_to lh(:Japanese), recursive_path(locale: :ja)
recursive_path および lh はすべての view で使えるように app/helpers/application_helper.rb にメソッドを記載します。また、リンク表示は常に lh メソッドを呼ぶことにします。とりあえず、今は名前の前後を大括弧で括ることにします。
module ApplicationHelper # 再帰パスを作成 def recursive_path(options = {}) request.symbolized_path_parameters.merge(@ids || {}).merge(options) end # link 文字列の作成 def lh(v) "[#{v}]" end end
ここまで記述すると、Gaurd も成功しますし、実際の画面でも日本語・英語の切替ができるようになっています。現在のものを heroku にもアップしてみました。取り急ぎ今日はここまで。