我有一个验证方法,必须验证在另一个方法中分配的值,如何让它在验证之前识别这些值? pay_must_be_same_to_amount方法需要create_items_from_readings方法中的一些值
class Invoice < ActiveRecord::Base
attr_accessible :approved_by, :due_date, :invoice_date, :reading_ids, :terms, :customer_id, :customer, :status, :reference_no, :payment_method, :amount, :payment_date
has_many :invoice_items, :dependent => :destroy
belongs_to :customer, :inverse_of => :invoices
validate :pay_must_be_same_to_amount
def create_item_from_readings
item = invoice_items.new
item.rate = customer.unit_cost
readings_in_this_period = customer.unbilled_readings.where('date_of_reading <= ?', invoice_date).order(:date_of_reading)
return nil if readings_in_this_period.empty?
self.reading_ids = readings_in_this_period.collect(&:id).join(',')
total_units = 0
readings_in_this_period.each do |reading|
total_units = total_units + reading.units_used1 + reading.units_used2 + reading.units_used3
end
item.amount = total_units * customer.unit_cost * customer.ct_ratio
item.tax_amount = (item.amount * Settings.vat) if customer.pays_vat
invoice_from_reading = readings_in_this_period.first.previous_reading
invoice_from_reading ||= readings_in_this_period.first
invoice_to_reading = readings_in_this_period.last
#Select Item description based on Phase type
if customer.phase_type == 'Single Phase'
item.description = "Electricity used from #{invoice_from_reading.date_of_reading.strftime('%d/%m/%Y')} with readings #{invoice_from_reading.reading1} to #{invoice_to_reading.date_of_reading.strftime('%d/%m/%Y')} with reading #{invoice_to_reading.reading1} - #{total_units.to_i} total units"
else
item.description = "Electricity used from #{invoice_from_reading.date_of_reading.strftime('%d/%m/%Y')} with readings, R1: #{invoice_from_reading.reading1}, R2: #{invoice_from_reading.reading2}, R3: #{invoice_from_reading.reading3} to #{invoice_to_reading.date_of_reading.strftime('%d/%m/%Y')} with readings, R1: #{invoice_to_reading.reading1}, R2:#{invoice_to_reading.reading2}, R3: # {invoice_to_reading.reading3}- #{total_units.to_i} total units"
end
end
end
并且验证方法如下,需要将上面的item.amount与类Invoice中的金额进行比较
def pay_must_be_same_to_amount
if item.amount < self.amount && item.amount != self.amount
self.errors.add :amount, 'The payment amount should be equal to amount on invoice'
end
end
end
答案 0 :(得分:0)
一些评论:create_item_from_readings
太复杂了。我不知道它应该做什么,但如果你运行它,我相信它会返回一个字符串(上一个if
语句中的两个之一)。
如果您需要做的就是将item.amount
与发票amount
属性进行比较,那很简单。您几乎可以在编写时使用验证方法,并根据需要使用其他一些方法。
def item_amount
total_units * customer.unit_cost * customer.ct_ratio
end
def total_units
readings_in_this_period.inject(0) {|total,r| total + r.units_used1 + r.units_used2 + r.units_used3 }
end
def pay_must_be_same_to_amount
if item_amount != amount
errors.add :amount, 'The payment amount should be equal to amount on invoice'
end
end
这两种补充方法的代码只是用较长方法修改的代码。
一个好的实践规则是,如果一个方法长于一行,并且你无法通过浏览它来判断它是什么,它太长了(这不是总是为真,但是考虑到复杂的方法,这是值得的。)
答案 1 :(得分:0)
问题的解决方案是
def pay_must_be_same_to_amount
sum = 0
self.invoice_items.each do |invoice_item|
sum = sum + invoice_item.amount
end
if sum != self.amount
self.errors.add :amount, 'The payment amount should be equal to amount on invoice'
end
end