細かく書きすぎると肝心なところが抜けてしまうので、これまでと同じところは省略していきます。特に locales のところは記述しませんので、適当に補完して下さい。
タイトルの編集
引き続き、編集・更新のコントローラを作成します。いつものようにテストから記述します。
シナリオ: 開発環境でタイトルを編集する 前提 タイトルにダミーデータを登録する もし タイトル一覧を表示する かつ id が "あいうえお" である行の "[編集]" をクリックする ならば 画面に "タイトル編集(あいうえお)" と表示されていること もし "日本語" に "森高 千里" と入力する かつ "英語" に "Chisato Moritaka" と入力する かつ "読み" に "もりたか ちさと" と入力する かつ "更新する" ボタンをクリックする ならば 画面に "タイトル一覧" と表示されていること かつ 画面に "森高 千里" と表示されていること
ダミーデータの登録 step は spec/acceptance/steps/titles_page_steps.rb に記述します。
step 'タイトルにダミーデータを登録する' do Title.create(japanese:'あいうえお', english:'AIUEO', yomi:'あいうえお') end
また、テーブルの特定行のリンククリックに関する step は spec/acceptance/steps/top_page_steps.rb に記述します。
step 'id が :name である行の :link をクリックする' do |name, link| within("//tr[@id='#{name}']") do click_link link end end
view においてタイトルリストの id の設定ができていないこと、編集リンクがないことからエラーになっています。このため app/views/titles/index.html の該当部を以下のように修正します。
%table %tr -%w(link.titles).each do |k| %th=t k -if @is_dev %th=t 'head.control' -@titles.each do |title| -name = title.name(@is_ja) %tr{id:name} %td=name -if @is_dev %th=link_to lh(t 'link.edit'), edit_title_path(title)
編集リンクにより、edit が呼ばれました。app/controllers/titles_controller.rb に edit を記述します。今後作成する edit, update, destroy, show ではすべて id で指定されたタイトルオブジェクトを取得するため、app/controller/titles_controller.rb に before_action を追加します。
class TitlesController < ApplicationController before_action :reject_production, except:[ :index, :show ] before_action :get_title, only:[ :edit, :update, :destroy, :show ]
get_title は private メソッドとして実装します。
def get_title @title, @ids = get_objects_and_ids [ Title ] end private :get_title
ここに記述した get_objects_and_ids は他のコントローラでも使用するため、app/controllers/application_controller.rb に記述します。
def get_objects_and_ids(array, first_id = true) ans = [] ids = {} array.each_with_index do |model, i| id = i == 0 && first_id ? 'id' : "#{model.to_s.underscore}_id" if pid = params[id] ans << model.find(pid) ids[id] = pid else ans << nil end end ans << ids end
最後に、edit メソッドを app/controllers/titles_controller.rb に記述します。@title を取得するだけなので、中身は何もありません。
def edit end
app/views/titles/edit.html.haml を記述します。
%h1="#{t '.title'}(#{@title.name(@is_ja)})" =render partial:'form'
当初、app/views/titles/_form.html.haml に書いた時には f.submit にボタン名の引数を付けていましたが、以下のように省略すると文脈から適切なボタン名が付けられるのですね。
%td{colspan:2}=f.submit
今回は edit なので自動的に「更新する」に変更されています。この結果、テストの方は無事に update メソッドが呼ばれていることがわかります。update メソッドも通常通り作成してしまいます。
def update if @title.update(title_params) redirect_to titles_path(head:@title.head) else render action: :edit end end
正しく、テストが通過しました。編集に失敗した場合のテストもしておきます。登録自と違うのは前提とボタン名だけですね。
シナリオ: パラメータ設定が間違えていたときのエラー確認(タイトル編集) 前提 タイトルにダミーデータを登録する もし タイトル一覧を表示する かつ id が "あいうえお" である行の "[編集]" をクリックする もし "日本語" に "" と入力する かつ "英語" に "Chisato Moritaka" と入力する かつ "読み" に "もりたか ちさと" と入力する かつ "更新する" ボタンをクリックする ならば 画面に "タイトル一覧" と表示されていないこと かつ 画面に "日本語を入力してください。" と表示されていること もし "日本語" に "森高 千里" と入力する かつ "英語" に "" と入力する かつ "更新する" ボタンをクリックする ならば 画面に "タイトル一覧" と表示されていないこと かつ 画面に "英語を入力してください。" と表示されていること もし "英語" に "Chisato Moritaka" と入力する かつ "読み" に "" と入力する かつ "更新する" ボタンをクリックする ならば 画面に "タイトル一覧" と表示されていないこと かつ 画面に "読みを入力してください。" と表示されていること かつ "読み" に "ABC" と入力する かつ "更新する" ボタンをクリックする ならば 画面に "タイトル一覧" と表示されていないこと かつ 画面に "読みは不正な値です。" と表示されていること
このテストはちゃんと通過しますね。
タイトル削除
タイトルが他のオブジェクトと関連していない場合、タイトルが削除できるようにします。現在は他のクラスがないため、すべて削除できる状況です。削除のテストを書いてみます。
シナリオ: 開発環境でタイトルを削除する 前提 タイトルにダミーデータを登録する もし タイトル一覧を表示する かつ id が "あいうえお" である行の "[削除]" をクリックする かつ ダイアログを承認する ならば 画面に "タイトル一覧" と表示されていること かつ 画面に "あいうえお" と表示されていないこと
削除リンクを app/views/titles/index.html.haml に追加します。
-if @is_dev %th =link_to lh(t 'link.edit'), edit_title_path(title) =link_to lh(t 'link.destroy'), title_path(title), method: :delete, data:{ confirm:t('confirm.destroy') } if title.can_delete?
@title が削除できるかどうかは app/models/title.rb の can_delete? というメソッドで判断します。今は常に true を返します。
def can_delete? true end
ダイアログの承認までが実行でき、destroy メソッドがないとエラーになっています。
def destroy head = @title.head @title.destroy redirect_to titles_path(head:head) end
これを記述して削除まで実装できました。show は今のところ表示するものがあまりないため、別のクラスを作成した後に作成してみます。