是否可以覆盖一个方法而仍然回退到原始方法(如果不涉及任何超类)?
def User
def method
# do some original stuff
end
def method
# do some new stuff
call_the_original :method
end
end
希望我的具体例子可以使我的意思更清楚。
在用户模型中使用活动存储has_one_attached :avatar
将添加一个setter方法。调用此setter时,我想做一些事情,但我仍然希望运行原始方法。
class User
has_one_attached :avatar
# According to the source (see references) this mixes in the following setter method
def avatar=(attachable)
# do activestorage stuff
end
# I want to add some custom functions to this, before still running "do activestorage
# stuff". I could copy, paste and edit the entire function. But out of interest,
# I wondered if a more elegant solution exists.
def avatar=(attachable)
# do my stuff
super(attachable)
end
end
super
显然不起作用,因为用户没有从定义了avatar=()
的任何内容继承。
我可以创建例如包含MasterUser
且继承自has_one_attached
的{{1}}类,但是对于这种特殊情况,这似乎有些过分。
我可以提交给User
的{{1}} >
但是对于这个问题,我真正感兴趣的是是否有一种方法可以从同名方法中调用先前定义的方法?
参考:
答案 0 :(得分:3)
您可以在此处使用alias_method
来访问先前的定义:
class User
def avatar=(attachable)
# do activestorage stuff
end
alias_method :original_avatar=, :avatar=
def avatar=(attachable)
# do my stuff
self.original_avatar=(attachable)
end
end
答案 1 :(得分:2)
另一种选择是将旧方法保存在变量中,然后再定义具有相同名称的新方法。然后从新定义的方法内部调用变量:
class User
def avatar=(attachable)
# do activestorage stuff
end
instance_method(:avatar=).tap do |avatar_eq|
define_method(:avatar=) do |attachable|
# do my stuff
avatar_eq.bind(self).call(attachable)
end
end
end
在上面的示例中,必须使用define_method(:avatar=)
,因为常规的def avatar=
不允许您访问avatar_eq
变量。
代码比JagdeepSinghs answer复杂一些,但是使类的方法不那么混乱。不再定义旧方法,因此无法再单独调用。
参考:
Module#instance_method
获取先前定义的方法Object#tap
将变量命名为类定义的一小部分Module#define_method
来定义具有相同名称的新方法UnboundMethod#bind
将未绑定的方法绑定到当前的User
实例Method#call
调用绑定的先前定义的方法