タイトルコントローラの作成(1)

今回の作業を行っていく上で config/locales/views/*.yml の変更時に Guard が反応しませんでした。Guardfile に以下の行を追加します。

  watch(%r{^config/locales/views/(.+)\.yml$})          { "spec" }

また、haml を修正時には feature を実行したいので、同様に Guardfile を修正します。

  watch(%r{^app/views/(.*)/.*\.html\.haml$})          { |m| "spec/acceptance/#{m[1]}_page.feature" }

仕様策定

モデルができたので、コントローラを作成していきます。先に仕様を考えます。

  • タイトル一覧は読みの先頭文字「あ」〜「ん」で表示を分離(濁点、半濁点はページを共有)
  • 関係者、曲、アルバム、シングルなどへのリンクを表示(ただしそれぞれのページができてから)
  • 運用環境では閲覧のみ
  • 開発環境では CRUD を全て実装
  • トップページ及びトップリンクにタイトル一覧へのリンクを用意

一覧表示の作成

まず、一覧表示のページ遷移の feature を書きます。

# encoding: utf-8
# language: ja
機能: タイトルに関する CRUD を確認する
  シナリオ: タイトルページにアクセスする
    前提 トップページを表示する
    もし "[タイトル]" をクリックする
    ならば 画面に "タイトル一覧" と表示されていること

当然ながら[タイトル]というリンクがないのでエラーになります。

     Failure/Error: もし "[タイトル]" をクリックする
     Capybara::ElementNotFound:
       Unable to find link "[タイトル]"

app/views/shared/_top_link_bar.html.haml に titles_path へのリンクを追加します。

%table
  %tr
    %td=link_to lh(t 'link.home'), root_path
    %td=link_to lh(t 'link.titles'), titles_path

また、config/locales/views/ja.yml, config/locales/views/en.yml も更新しておきます。

  link:
    home: 'ホーム'
    titles: 'タイトル'
  link:
    home: 'Home'
    titles: 'Titles'

まだ routing 設定をしていないので、以下のようにエラーとなります。

     Failure/Error: もし "[タイトル]" をクリックする
     ActionView::Template::Error:
       undefined local variable or method `titles_path' for #<#<Class:0x007fb41ecc8308>:0x007fb41e92b718>

config/routes.rb に titles に関する routing 情報を追加します。今回は、CRUD を全部設定する予定なので、フィルタリングは行いません。

MoritakaDb::Application.routes.draw do
  root 'top#index'
  resources :titles
end

Guard の結果は以下のようになります。

     Failure/Error: もし "[タイトル]" をクリックする
     ActionController::RoutingError:
       uninitialized constant TitlesController

TitlesController がないと言われるので、generator で作成します。

r g controller titles

Guard の結果は以下のようになります。

     Failure/Error: もし "[タイトル]" をクリックする
     AbstractController::ActionNotFound:
       The action 'index' could not be found for TitlesController

index がないので、app/controllers/titles_controller.rb にメソッドを作成します。取り急ぎ中身は空にしておきます。

  def index
  end

こんどは view がないというエラーになります。

     Failure/Error: もし "[タイトル]" をクリックする
     ActionView::MissingTemplate:
       Missing template titles/index, application/index with {:locale=>[:ja], :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"

とりあえず、app/views/titles/index.html.haml にタイトルだけ表示します。top/index と同じ表記です。

%h1=t '.title'

ローカライズされていないので、Title とだけ表示されており、エラーになっています。

     Failure/Error: もし "[タイトル]" をクリックする
       expected to find text "タイトル一覧" in "[ホーム] [タイトル] [English] Title"

ローカライズを追加することでテストを通過させます。

  titles:
    index:
      title: "タイトル一覧"
  titles:
    index:
      title: "List of titles"

これでテストが通過しました。

開発環境と運用環境

今回、開発環境では編集を可能とし、運用環境では閲覧のみを行うことにしました。そこで、production 環境以外(development, test) においては、@is_dev という変数を true とすることにします。locate の設定のために、app/controllers/application_controller.rb にて set_locale というメソッドを before_action しているので、その時に一緒に設定することにします。

  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
    @is_ja = I18n.locale == :ja
    @is_dev = ! Rails.env.production?
  end 

まず、運用環境でタイトルが追加できなくなっているかをテストします。

  シナリオ: 運用環境ではタイトル追加ができない
    前提 運用環境である
    かつ タイトル一覧を表示する
    ならば 画面に "[タイトル追加]" と表示されていないこと

これらの step を書いていきます。最初の最後の step はどこでも使用することがあるため、top_page_steps.rb に記載することにします。本来なら共通部品用の steps を書くべきなのかもしれません。

step '画面に :string と表示されていないこと' do |string|
  expect(page).not_to have_content(string)
end

step "運用環境である" do
  Rails.stub_chain(:env, :production).and_return(true)
  Rails.stub_chain(:env, :development).and_return(false)
end

その後、spec/acceptance/steps/titles_page_steps.rb を記載します。

# encoding: utf-8        
                         
step 'タイトル一覧を表示する' do
  visit titles_path      
end

そもそも、タイトル追加と書いていないのでテストは通過しています。引き続き app/views/titles/index.html.haml にタイトル追加リンクを記述してみます。まずは普通に書いてエラーになることを確認します。また、両方の locales に titles: new: title: を追加しておきます。

%h2=t 'titles.new.title'
%table           
  %tr            
    %td=link_to lh(t 'titles.new.title'), new_title_path

Guard でエラーになりました。タイトル追加のリンクが表示されているのであたりまえですね。運用環境でこのリンクが表示されないように、@is_dev の時のみ表示するようにします。

-if @is_dev
  %h2=t 'titles.new.title'
  %table
    %tr
      %td=link_to lh(t 'titles.new.title'), new_title_path

これで開発環境と運用環境で処理が別れていることがわかります。長くなってしまったのでこの続きは後日。

written by iHatenaSync