简体   繁体   English

如何对彼此依赖的两个属性运行回调函数?

[英]How to run a callback function on two attributes that depend on each other?

In my Rails app I have an Invoice model with the attributes date and due_date . 在我的Rails应用程序中,我有一个具有datedue_date属性的Invoice模型。

For reasons of simplicity I don't want the user to manually enter the due_date but rather simply enter the number of days that should be added to the date . 为了简单起见,我不想用户手动输入due_date ,而只是输入应该添加到date 的天数

This is why I set up a virtual attribute days_allowed . 这就是为什么我设置虚拟属性days_allowed

class Invoice < ActiveRecord::Base

  belongs_to :user

  before_save :save_date

  attr_accessor :days_allowed

  def days_allowed # attribute reader (I need that too!)
    (due_date - date).to_i
  end

  def save_date
    self.due_date = date + days_allowed.days
  end

end

However, when a user picks a date in the form and enters a number of days, eg 10 , I get wrong results because the save_date callback refers to the days_allowed method rather than the attribute of the same name. 但是,当用户在表单中选择一个日期并输入天数(例如10 ,我会得到错误的结果,因为save_date回调引用的是days_allowed方法,而不是同名的属性。

The key problem seems to be that I am using the callback on two different attributes that depend on each other ( date and days_allowed ). 关键问题似乎是我对彼此依赖的两个不同属性( datedays_allowed )使用了回调。

Can anybody tell me how to solve this puzzle? 谁能告诉我如何解决这个难题?

Thanks for any help. 谢谢你的帮助。

How about this approach (no before_save is necessary): 这种方法怎么样(不需要before_save ):

class Invoice < ActiveRecord::Base

  belongs_to :user

  def days_allowed
    (due_date - date).to_i
  end

  def days_allowed=(days)
    self.due_date = date + days
  end
end

EDIT Not supposed to work with mass assignment when both date and days_allowed are present unless date always goes first. 编辑如果datedays_allowed都存在, days_allowed应该使用批量分配,除非date始终排在最前面。

I think you need to store all three fields, just not provide any form attributes for editing the calculated one. 我认为您需要存储所有三个字段,只是不提供任何用于编辑计算字段的表单属性。

While your use-case at it is might seem like this is a violation of 'don't repeat yourself', I think this is an instance of coincidental duplication. 虽然您的用例似乎违反了“不要重复自己”,但我认为这是巧合重复的一个实例。 Let me explain: 让我解释:

Consider your next problem - you are going to start having due dates on weekends, holidays, etc. For exactly that reason I wrote the business_time gem: 考虑您的下一个问题-您将开始在周末,假期等开始安排到期日。正是出于这个原因,我编写了business_time gem:

https://github.com/bokmann/business_time https://github.com/bokmann/business_time

so in your solution where you add 10 days, you can now add 10 business days. 因此,在您添加10天的解决方案中,您现在可以添加10个工作日。 The exact due date can now fluctuate across weekends, 3-day weekends created by holidays, etc. And if you have to deal with snow days, like most of the East Coast of the US has had to lately, you can just add tham as a holiday and recalculate. 现在,确切的到期日期可能会在周末,假期创建的3天周末等之间波动。如果您不得不处理下雪天,例如美国东海岸的大多数地区最近都必须这样做,则可以将tham添加为放假然后重新计算。 The number of business days is still 10, but the due date has changed. 工作日仍为10个工作日,但截止日期已更改。 The number of business days was a critical piece of data to save, not a piece of data to calculate. 工作日数是要保存的关键数据,而不是要计算的数据。 The due data needs to be saved, because its a piece of information calculated in a context that you'll want to save for querying rather than try to recalculate every time. 需要保存到期数据,因为它是在上下文中计算出的一条信息,您希望将其保存以进行查询,而不是每次都尝试重新计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM