[英]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应用程序中,我有一个具有
date
和due_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
). 关键问题似乎是我对彼此依赖的两个不同属性(
date
和days_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. 编辑如果
date
和days_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.