[英]Calling super on a method defined by define_method
I have created a Model class where I define methods based on a method (attribute) called in User (which inherits from Model). 我创建了一个Model类,我根据在User中调用的方法(属性)定义方法(继承自Model)。 The problem is that I cannot override the method defined by define_method, and call super to pass to the defined method. 问题是我无法覆盖define_method定义的方法,并调用super来传递给定义的方法。 I guess this is because the defined method is added to User itself, and not to the Model, so it actually has no method in the superclass (ie Model). 我想这是因为定义的方法被添加到User本身,而不是模型,所以它实际上没有超类中的方法(即模型)。
The reason I want to do this is because most attributes should be saved to the database directly, while some attributes, like password, needs some additional processing. 我想这样做的原因是因为大多数属性应该直接保存到数据库中,而某些属性(如密码)需要一些额外的处理。
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>'
Is there any way I could change the code to get this working? 有什么办法可以改变代码来实现这个目的吗? I need a way to override dynamically created methods. 我需要一种方法来覆盖动态创建的方法。
Define the method on the superclass
: 在superclass
上定义方法:
class Model
def self.attribute(name)
superclass.send :define_method, name do
self
end
end
end
The way Rails deals with this is that there are multiple ways to get attributes. Rails处理这个问题的方法是有多种获取属性的方法。 One of these is (by convention) never overridden so it can be used in your defined methods: 其中一个(按惯例)从未被覆盖,因此可以在您定义的方法中使用它:
# 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
Using superclass.send :define_method
might lead to some unexpected behaviour, because that method would be available to every Model
subclasses. 使用superclass.send :define_method
可能会导致一些意外行为,因为该方法可用于每个Model
子类。
It is well described in this article https://thepugautomatic.com/2013/07/dsom/ 本文详细介绍了https://thepugautomatic.com/2013/07/dsom/
So following this article you could define your attribute
method like this 因此,按照本文,您可以像这样定义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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.