改良中...フォームのエラー表示も含めた検証(validate)に変更

前回からの改良作業の続き。気付いたところから、より使い易く、よりメンテし易くなるようにどんどん変更していく。今回は、伝票と明細の合計金額の検証のところ。現状は検証エラーが発生しても、エラーメッセージしか表示しない。改良後は伝票の合計金額と、入力のある行の明細の金額で、お馴染みの赤枠で囲う強調表示もするようにしてみた。

  • journals_valid?、journals_total_yenメソッドを定義することで、コードが理解し易くなった気がする。
# モデル: app/models/slip.rb
class Slip < ActiveRecord::Base
  has_many :journals, :order=>:position, :dependent=>:destroy
  validates_presence_of :number, :executed_on, :total_yen

  def validate
    # 明細の入力チェック
    errors.add_to_base("明細が一行も入力されていません。") unless journals_valid?
    # 合計金額のチェック
    # nilが含まれると数値として取り扱えないので、to_iで数値に変換しておく必要あり
    errors.add(:total_yen, "が明細の合計と一致していません。") unless total_yen.to_i == journals_total_yen
  end

  def journals_valid?
    @editing_journals.inject(false) {|result, journal| result || journal.input?}
  end

  def journals_total_yen
    @editing_journals.sum {|journal| journal.yen.to_i} unless @editing_journals.blank?
  end
...(中略)...
end
# モデル: app/models/journal.rb
class Journal < ActiveRecord::Base
  belongs_to :slip
  validates_presence_of :comment, :yen

  def validate
    errors.add(:yen, "が合計金額と一致していません。") unless slip.total_yen.to_i == slip.journals_total_yen
  end
...(中略)...
end
  • 最初、以下のようにSlipモデルの中で明細(Journalインスタンス)の検証をしていた。しかし、これだと思った通りの検証結果にならない...。(journal.valid?を実行する時、それまでの検証エラーが一旦クリアされるため?)上記のように、Journalインスタンスの検証はJournalモデルの中で処理することで、うまく動くようになった。
# モデル: app/models/slip.rb
class Slip < ActiveRecord::Base
...(中略)...
  def validate
    unless total_yen.to_i == journals_total_yen
      errors.add(:total_yen, "が明細の合計と一致していません。")
      @editing_journals.each do |journal|
        journal.errors.add(:yen, "が合計金額と一致していません。") if journal.input?
      end
    end
  end
...(中略)...