【Ruby on Rails】テーブルに無い項目をフォームで扱う場合【学習記録4】
2013.10.20
引き続きRailsの勉強。
例えば前回までにつくった「article」モデルの「掲載期限」について、「掲載期限を指定しない」というチェックボックスを追加する場合を考える。チェックがされている場合は 掲載期限を保存しない。
この場合 テーブルの項目として新たにカラムを一つ追加するのも無駄があるので、アクセサメソッドを使用する。
まずはViewに変更を加える。 articles/_form.html.erb の掲載期限の部分に対し、noexpire というチェックボックスを実装。
<td> <%= form.check_box :noexpire %> <%= form.label :noexpire %><br> <%= form.date_select :expired_at, start_year: 1990, end_year: 2030, use_month_numbers: true %></td>
Articleモデルに以下のアクセサメソッドを追加。
def noexpire expired_at.blank? end def noexpire(=val) @noexpire = val.in?([1,"1",true]) end
フォーム項目と同名のアクセサメソッドを定義した。getterの方では フォームをページで読み込んだ際に返す値を記述し、setterの方では フォームをPOSTする際に @noexpire というインスタンス変数に対して「フォームから渡された値が 1,”1″,true のいずれかならtrue、そうでなければfalse」を代入。
ここでバリデーションが実行される前に行われる処理を記述する。
before_validation :fix_expired_at : (略) : def fix_expired_at self.expired_at = nil if @noexpire end
fix_expired_at では、POST時にsetterで定義された@noexpireの値がtrueなら(つまり「掲載期限を指定しない」にチェックされた状態なら)、データベースに格納する expired_at の値を「nil」にする、という処理が行われている。
因みに、何故ここに「self」をつける必要があるのか?以下のようにしてもいいんじゃないの?
def fix_expired_at expired_at = nil if @noexpire end
…と思ったけれど、上記がダメな理由は Ruby の根本原則を考えると自明で、上記のようにすると expired_at が 一関数内のローカル変数になってしまう という単純な理由だった。
Written by Nisei Kimura ( 木村 仁星 )