我有两个模型,一个存储事件,另一个是日历模型的连接模型。连接模型与远程Calendar API集成,并在创建或删除时通过API调用自行管理(通过before_save和before_destroy回调)。
当一次删除一个连接模型记录时,这很有用,但由于我已经依赖于::在我的事件模型中定义的has_many关联上销毁(我不希望远程日历中的孤立事件),删除单个事件将导致N api调用(其中N是连接模型记录的数量,假设可能是数千个),这很容易导致超时。
理想情况下,我想延迟CalendarEvent.destroy调用,但仅限于从删除事件调用它时。例如:
Event.destroy [在所有CalendarEvent(连接模型)记录上调用delay.destroy] CalendarEvent.destroy [destroy without delayed_job]
有没有办法通过has_many调用来延迟这个?
有没有办法通过依赖传递自定义destroy方法:?
在CalendarEvent.destroy方法中,是否有办法知道是否从依赖的:: destroy定义调用它?
答案 0 :(得分:1)
有没有办法通过has_many调用来延迟这个?
没有。
有没有办法通过依赖传递自定义destroy方法:?
也没有; the docs中只有少数已接受的选项:
:destroy导致所有相关对象也被销毁。
:delete_all导致所有关联对象直接从数据库中删除(因此不会执行回调)。
:nullify导致外键设置为NULL。回调不会被执行。
:如果存在任何关联记录,restrict_with_exception会引发异常。
:如果存在任何关联对象,restrict_with_error会将错误添加到所有者。
在CalendarEvent.destroy方法中,是否有办法知道是否从依赖的:: destroy定义中调用它?
你可以在技术上嗅探caller
中的堆栈轨迹,但这听起来并不是一个好主意。
我删除dependent:
选项并构建一个自定义after_destroy
,以延迟方式清理CalendarEvent
个对象。
after_destroy :destroy_calendar_events
def destroy_calendar_events
calendar_events.each {|event| event.delay.destroy }
end
很久以前,我工作的一家公司用Async Observer解决了这个问题,它提供了async_destroy
方法,但这是基于Beanstalk的,需要进行调整。如果你想烘烤一些东西,代码可能会很有趣。
答案 1 :(得分:1)
Kristján的答案可能会奏效,但我遇到了外键问题。没有依赖的外键::: destroy不想工作。
然后我遇到了delayed_job的问题,如果我试图延迟API服务对象本身,想要在DB条目中存储我的延迟作业的RSA密钥。让人惊讶。它无论如何都没有验证(空)键,所以它在2个方面失败了。
然后我尝试在创建新API对象的对象实例上延迟一个方法。当然它失败了,因为延迟的作业试图加载对象(已经被破坏)来运行作业。咂额头,尖叫,拉头发,重复。
最终工作的是调用类方法(或者它实际上可能是外部服务对象等),只传入字符串(不计入任何可以删除的对象以提供必要的信息)。
class CalendarEvent
# bunch o' stuff
def destroy
self.class.delay.remove_remote_event!(user, remote_calendar_id, remote_id)
super
end
def self.remove_remote_event!(user, remote_calendar_id, remote_id)
EpGoogle::Interfaces::Calendar.new(user.email).delete_event(remote_calendar_id, remote_id)
end
end
...然后DelayedJob能够成功运行任务。
它并不像我想的那样棒,因为如果作业失败,远程事件可能会孤立,但对我的用例来说这已经足够了。