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