Ruby 1.9.3 - > 2.0 alias_method并扩展

时间:2013-11-21 00:25:13

标签: ruby-on-rails ruby activerecord ruby-2.0

我正在尝试将Ruby 1.9.3应用程序升级到2.0,除了一次打嗝之外,一切似乎都很顺利。我写了一个模块,我在模型中包含了覆盖activerecord destroy的模块。它将现有destroy方法别名为destroy!,然后覆盖destroy以更改记录上的deleted_at时间戳。只有当我升级到ruby 2.0 destroy!时才会破坏记录,但行为就像我的新覆盖方法一样。知道为什么会这样吗?代码的相关部分如下。完整的要点here

  def self.included(base)                                                          
    base.class_eval do                                                             
      alias_method :destroy!, :destroy                                             
      alias_method :delete!, :delete                                               
      default_scope -> { where(:deleted_at => nil) }                               
    end                                                                            

    base.send :extend, ClassMethods                                                
    base.send :include, InstanceMethods                                            
  end

3 个答案:

答案 0 :(得分:1)

查看paranoia gem。这是一个Rails 3/4兼容的软删除实现,可以完成你所追求的目标。如果您只想提供软删除,那么我将使用gem并完成它。如果你希望自己实现软删除,那么实现可以为你提供一些关于它之前是如何完成的见解。

答案 1 :(得分:0)

如果您为当前类中未直接定义的方法添加别名,则alias会在执行该类的类的最近祖先中查找该方法。

当您将Trashable::InstanceMethods包含在其中一个模型中时,它会插入该模型的祖先链的前面。因此,在该模型中调用destroy!会触发destroy上的Trashable::InstanceMethods方法。

如果您将def destroyInstanceMethods移到base.class_eval,那么它将直接在包含模型中定义,并且包含'destroy'的该模型的最近祖先将是ActiveRecord中的相关模块。因此,调用destroy!会按预期触发SQL DELETE

请参阅class.ancestors以进一步探讨此行为。

答案 2 :(得分:0)

在Ruby 2.0中,他们引入了预先添加模块的概念,因此您可以在模型和ActiveRecord :: Base之间插入行为。我建议将代码移动到模块中,而不是包含该模型,您可以将其添加到模块中。从别名方法中保存。

以下是一些与新前置功能相关的文章:

https://gist.github.com/mattetti/5104790

http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html

http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html