在define_method定义的方法上调用super
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在define_method定义的方法上调用super相关的知识,希望对你有一定的参考价值。
我创建了一个Model类,我根据在User中调用的方法(属性)定义方法(继承自Model)。问题是我无法覆盖define_method定义的方法,并调用super来传递给定义的方法。我想这是因为定义的方法被添加到User本身,而不是Model,因此它实际上没有超类中的方法(即Model)。
我想这样做的原因是因为大多数属性应该直接保存到数据库中,而某些属性(如密码)需要一些额外的处理。
class Model
def self.attribute(name)
define_method(name) do
self
end
end
end
class User < Model
attribute :password
end
class User2 < Model
attribute :password
def password
super
end
end
@user = User.new
puts @user.password # => <User:0x00000100845540>
@user2 = User2.new
puts @user2.password
# define_super.rb:17:in `password': super: no superclass method
# `password' for #<User2:0x00000100845578> (NoMethodError)
# from define_super.rb:25:in `<main>'
有什么办法可以改变代码来实现这个目的吗?我需要一种方法来覆盖动态创建的方法。
答案
在superclass
上定义方法:
class Model
def self.attribute(name)
superclass.send :define_method, name do
self
end
end
end
另一答案
Rails处理这个问题的方法是有多种获取属性的方法。其中一个(按惯例)从未被覆盖,因此可以在您定义的方法中使用它:
# This method is never overridden, but also rarely used as a public method
def[](key)
# Returns value of `key` attribute
end
# This is the effective default implementation of an attribute
def att1
self[:att1]
end
# This shows how you can have custom logic but still access the underlying value
def att2
self[:att2] unless self[:att2].empty?
end
另一答案
使用superclass.send :define_method
可能会导致一些意外行为,因为该方法可用于每个Model
子类。
这篇文章很好地描述了https://thepugautomatic.com/2013/07/dsom/
因此,按照本文,您可以像这样定义attribute
方法
class Model
MODULE_NAME = :DynamicAttributes
def self.attribute(name)
if const_defined?(MODULE_NAME, _search_ancestors = false)
mod = const_get(MODULE_NAME)
else
mod = const_set(MODULE_NAME, Module.new)
include mod
end
mod.module_eval do
define_method(name) do
self
end
end
end
end
以上是关于在define_method定义的方法上调用super的主要内容,如果未能解决你的问题,请参考以下文章