1

私は財務を記録Interactionsしており、偶数としてモデル化されておりLedgerEntries、それぞれの全体のInteraction合計はゼロでなければなりません。

class Interaction < ActiveRecord::Base
  has_many :entries, class_name: 'LedgerEntry'

  validate :entries_must_sum_to_zero

  def balance
    credit = self.entries.sum(:credit)
    debit = self.entries.sum(:debit)
    return credit - debit
  end

  protected

  def entries_must_sum_to_zero
    if self.entries.count.odd?
      errors.add(:entries, "There must be an even number of entries.")
    end
    if self.balance != 0
      errors.add(:entries, "Entries must sum to zero.")
    end
  end
end

class LedgerEntry < ActiveRecord::Base
  validates_numericality_of :credit, greater_than_or_equal_to: 0
  validates_numericality_of :debit, greater_than_or_equal_to: 0
  belongs_to :interaction

  validate :one_of_credit_or_debit

  protected

  def one_of_credit_or_debit
    if self.credit != 0 && self.debit != 0
      errors.add(:credit, "You can't assign both a credit and debit to the one entry.")
    end
  end
end

私が抱えている問題は、このテストが決して失敗しないことです。

it "should complain if an Interaction's balance is non-zero" do
  d = LedgerEntry.create!(credit: 50.0)
  expect {Interaction.create!(entries: [d])}.to raise_error ActiveRecord::RecordInvalid
end

の実行中entries_must_sum_to_zero self.entries.countは常に 0 であり、常に 0 をself.balance返します。

検証メソッドを実行する前にエントリを強制的に取得するにはどうすればよいですか?

4

2 に答える 2

1

検証では、検証を行うためにデータベース操作を使用していますが (つまりcountsum)、エントリはまだデータベースに保存されておらず、Interactionが保存されて外部キーと共に保存できるようになるまで保存されません。 .

ただし、プロキシentriesの魔法により、属性にアクセスして操作することはできます。データベースへのアクセスに依存ActiveRecordしない操作を使用する必要があるだけです。lengthcountto_a.map(&:<attribute>).inject(&:+)sum

  def balance
    credit = self.entries.to_a.map(&:credit).inject(&:+)
    debit = self.entries.to_a.map(&:debit).inject(&:+)
    return credit - debit
  end
于 2013-09-03T06:00:19.433 に答える