■外部キーの値をフォームから送る場合、一回受けてセットする形をとる。その際のポイント
【外部キーのセットをfind_by_文字列でなく、idでやる場合】
ちなみに、文字列でやる場合、例えば、面接枠の名前(外部キーが持つname属性)をフォームで送り、
それをコントローラで受けて、その名前をキーに外部キー対象を探し、リレーションをはるというおそまつ
な方法
文字列の場合は、例えばリストが何も選択されなかった場合、""で選択されてヒットしないので、
リレーションには勝手にnilが入るが、idでやった場合は、""が送られると、idには""が入り、m
find("")が行われてエラーする。よって、次のようにする
(interviewモデル内のコード) def set_relation_with_interviewer(id) unless id == "" interviewer = Interviewer.find(id) self.interviewer = interviewer end end ※検証で、interviewerをpresence_ofにすればいい、と思うかもしれないが、それは無理。 検証は、saveメソッドが行われた直後に起動するので、 @interview = Interview.new(params[:interview]) set_relations() → 上のset_relation_with_interviewer(id)を呼び出す if @interview.save
のように書くと、検証にかかる前に、エラーする。
また、先ほどのset_relation_with_interviewerメソッドにはバグがある。これだと、例えば更新の場合、
self.interviewerの値にもともと○○が入っていたとする。更新時に、これをnilに戻したいと思い、リスト
で空を選択し、updateした。
しかし、この時、id=""となるので、self.interviewerの値は更新されず、○○のままになってしまう。
これを回避するには以下のようにする。
def set_relation_with_interviewer(id) unless id == "" interviewer = Interviewer.find(id) self.interviewer = interviewer else self.interviewer = nil end end
ちなみに、この項目をビューで表示する場合、外部キーなので、interview.inteviewer.nameのように
書くだろう。しかし、interview.interviewerがnilの場合もあるので、<%=h interview.inteviewer.name if interview.inteviewer %>のようにする必要がある。