为1个模型字段使用2个虚拟属性

时间:2012-06-16 05:57:56

标签: ruby-on-rails ruby-on-rails-3

我是一名经验丰富的网络开发人员,但对rails很新。我正在编写一个基于复式会计数据库的预算申请。数据库包含表示事务的日记帐分录,每个日记帐分录都有多个过帐。每个帖子都有一个帐户和一个金额。我将借方金额表示为负数,将贷方金额表示为正数。

但是,我不希望用户记住正面和负面,所以我在模型上创建了信用额度和借记金额的虚拟属性,这样用户就可以看到单独的信用额度和借方金额字段。 / p>

发布模式如下:

class Posting < ActiveRecord::Base
  belongs_to :account
  belongs_to :journal_entry

  attr_accessible :account_id, :credit_amount, :debit_amount
  attr_accessor :credit_amount, :debit_amount

  after_validation :set_amount
  after_find :split_amount

  validates :credit_amount, :format => { :with => /\A(?:\d+(?:\.\d{1,2})?|(?:.\d{1,2}))?\z/ }
  validates :debit_amount,  :format => { :with => /\A(?:\d+(?:\.\d{1,2})?|(?:.\d{1,2}))?\z/ }

  validate :check_amounts

  def check_amounts
    unless @account_id.blank?
      if not @debit_amount.blank? and not @credit_amount.blank?
        errors.add(:base, "cannot specify both credit and debit amount.")
      elsif @debit_amount.blank? and @credit_amount.blank?
        errors.add(:base, "must specify one of credit or debit amount.")
      end
    end
  end

  protected

  def set_amount
    unless @debit_amount.blank? and @credit_amount.blank?
      self.amount = @debit_amount.blank? ? BigDecimal.new(@credit_amount) : -BigDecimal.new(@debit_amount)
    end
  end

  def split_amount
    @credit_amount = (self.amount.nil? or self.amount >= 0) ? self.amount : nil
    @debit_amount = (self.amount.nil? or self.amount >= 0) ? nil : -self.amount
  end
end

对于1个模型字段(金额),这是使用2个虚拟属性(credit_amount和debit_amount)的正确方法吗?我尝试直接使用底层金额字段的credit_amount / debit_amount编写getter和setter,但这意味着我无法准确地向用户报告验证错误。

1 个答案:

答案 0 :(得分:2)

我喜欢你写的方式。使用正则表达式的信用额度和借记金额验证比仅将这些字段验证为数字更严格。拆分金额方法可以使用上面的注释来解释你在那里做什么,以便下一个在凌晨3点调试的人不必弄明白(实际上,正则表达式也可以使用明确的描述注释)。 / p>

我希望这会有所帮助。

祝你好运!