Activerecord 在Rails 3中,使用around_destroy对数据库进行更新,而不是删除
我有一个数据库模型,其中有两个表,如下所示:Activerecord 在Rails 3中,使用around_destroy对数据库进行更新,而不是删除,activerecord,ruby-on-rails-3.1,callback,Activerecord,Ruby On Rails 3.1,Callback,我有一个数据库模型,其中有两个表,如下所示: date value_1 value_2 value_3 ---------------------------------- -infinity 5 6 7 12-01-2012 4 6 7 15-01-2012 4 7 8 16-01-2012 7 7 8 在应用程序中,数据(主要)用作单独的值;列中的不同值很重要: date
date value_1 value_2 value_3
----------------------------------
-infinity 5 6 7
12-01-2012 4 6 7
15-01-2012 4 7 8
16-01-2012 7 7 8
在应用程序中,数据(主要)用作单独的值;列中的不同值很重要:
date value_1 date value_2 date value_3
------------------ ------------------ ------------------
-infinity 5 -infinity 6 -infinity 7
12-01-2012 4 15-01-2012 7 15-01-2012 8
16-01-2012 7
这种设计带来了一些问题:我不能只是“插入”、“更新”和“删除”value_2
psuedo表的一些值,因为这可能会影响其他列中的值:如果我删除2012年1月15日的value_2
,删除整个记录将同时修改value_2
和value_3
psuedo表
这个问题(对我来说)的明显解决方案是使用回调来增强创建、更新和销毁操作的正确行为,使用around\uuu
回调。我为这些回调创建了一个类:
class TemporalCallbacks
def self.around_destroy(record)
# modify the record: replace it with the values from the previous entry
...
# do an update instead of the destroy
record.save
record.logger.debug "end of destroy callback"
end
def self.around_update(record)
...
end
end
class SomeModel < ActiveRecord::Base
...
around_update TemporalCallbacks
around_destroy TemporalCallbacks
...
end
我试图清空around_destroy回调,但这会导致相同的行为:在around_destroy回调之后的某个地方触发回滚
为什么会触发此回滚?如何修复此问题
我真的很想使用回调来解决这个设计问题:如果我不必在所有模型/控制器中构建更新而不是销毁,这将节省大量工作。我如何解决这个问题?当你向模型添加一个around\u destroy回调时,你需要屈服,这会屈服于before\uu和after\u回调,以及它所使用的销毁方法self.With before_uuu和after_uuu,您不需要屈服。将此添加到模型中时:
around_destroy { puts "in around"; yield; puts "out around" }
before_destroy { puts "before" }
after_destroy { puts "after" }
$ model.destroy
=> before
=> in around
=> (actual destroy happens here)
=> out around
=> after
要更改模型的实际销毁/删除行为,请查看,哪些记录存档而不是销毁
您可以像paranoid那样更改销毁和删除行为:
def destroy
_run_destroy_callbacks { delete }
end
def delete
self.update_attribute(:deleted_at, Time.now) if !deleted? && persisted?
freeze
end
这里有一个更简单的选择:
另外,请看这个问题:我终于找到了答案。我将保留另一个答案,因为它同样有效,但不会直接回答您的问题 必须使用around_destroy方法,如果不想删除记录,还必须将模型的销毁行为更改为不调用delete 有两种方法可用于周围环境: (1) 使用一个类:
class TemporalCallbacks
def self.around_destroy(model)
puts "TemporalCallbacks::around_destroy"
yield model
end
end
class SomeModel
around_destroy TemporalCallbacks
end
(2) 在模型中使用局部方法
class SomeModel
around_destroy :do_something
def do_something
puts "do_something"
yield
end
end
无论使用哪种解决方案,如果不想删除记录,还需要更改模型中的销毁方法:
class SomeModel
def destroy
_run_destroy_callbacks { puts "do nothing" }
end
通常情况下:
def destroy
_run_destroy_callbacks { delete }
end
你知道为什么会做出这样的选择吗?创建和更新行为可以通过所描述的方法完全改变,这使我能够让模型意识到我对数据有点奇怪的看法:around_create完全改变了创建行为。为什么开发人员在销毁后放置around_destroy,为什么不周围有相同的(更换)行为?事实上你是对的-around_destroy确实取代了destroy行为。我将更新我的答案。我可以将模型置于此“destroyed”状态,而不对数据库进行销毁吗?如果可能,这将是我问题的解决方案。我无法使用around_筛选器将模型置于销毁状态。重写模型的destroy方法允许我有一个环绕过滤器,如:谢谢。我最终得到了这个解决方案。
class SomeModel
def destroy
_run_destroy_callbacks { puts "do nothing" }
end
def destroy
_run_destroy_callbacks { delete }
end