似乎alias_method在类<<<<<<<<自我封锁,因为它在外面。具体来说,当我对实例方法使用alias_method并随后覆盖该方法时,可以使用别名来访问原始方法。但是,我无法使用类方法执行此操作。
这是我的用例:我重写了从ActiveRecord base继承的destroy和destroy_all方法,因为当前编写的代码使得在删除连接记录时很容易意外删除行。这个设计可能会随着一个更大的项目而改变,但是现在这是我的解决方案,因为在大多数情况下,没有人会想要从这个表中删除行。但为了仍然允许故意删除表中的行为善意,我使用alias_method以保留原始destroy和destroy_all方法的句柄。使用别名正在访问原始:destroy(实例)方法,但不允许我访问原始:desotry_all(类)方法
class HoldReason < ActiveRecord::Base
class << self
alias_method :remove_hold_reasons_from_table, :destroy_all
def destroy_all
raise "Nope"
end
end
alias_method :remove_hold_reason, :destroy
def destroy
raise "Nope"
end
end
在这里,我们看到虽然此策略适用于实例方法,但允许成功删除单行:
> HoldReason.find_by(title: "Management Review").remove_hold_reason
HoldReason Load (0.7ms) SELECT `hold_reasons`.* FROM `hold_reasons` WHERE `hold_reasons`.`title` = 'Management Review' LIMIT 1
(0.5ms) BEGIN
SQL (4.6ms) DELETE FROM `hold_reasons` WHERE `hold_reasons`.`id` = 23
(0.6ms) COMMIT
=> #<HoldReason id: 23, title: "Management Review", category: "Operations">
我无法访问原始:destroy_all方法来删除一个查询中的多行;相反,即使我使用别名,我也得到了重写方法:
> HoldReason.remove_hold_reasons_from_table
HoldReason Load (0.7ms) SELECT `hold_reasons`.* FROM `hold_reasons`
RuntimeError: Nope
对于类方法我似乎无法做到这一点,我怎么能修复它(除了使用原始SQL查询进行删除之外)?
答案 0 :(得分:0)
答案是我没有得到新的:destroy_all方法;我正确地得到了旧的:destroy_all方法,这称为:在引擎盖下销毁。当然,通过调用:destroy,它得到了new:destroy方法,它引发了错误。所以我似乎只是得到了新的类方法,因为新的类方法和新的实例方法引发了完全相同的错误。
如果我稍微修改一下,这会更清楚:
class HoldReason < ActiveRecord::Base
class << self
alias_method :remove_hold_reasons_from_table, :destroy_all
def destroy_all
raise "Don't destroy_all (multiple: class method)"
end
end
alias_method :remove_hold_reason, :destroy
def destroy
raise "Don't destroy (single: instance method)"
end
end
结果
> HoldReason.remove_hold_reasons_from_table
RuntimeError: Don't destroy (single: instance method)