4

我创建了一个模型类,我在其中定义基于在用户中调用的方法(属性)(继承自模型)的方法。问题是我无法覆盖define_method定义的方法,调用super传递给定义的方法。我猜这是因为定义的方法是添加到用户本身,而不是模型,所以它实际上在超类(即模型)中没有方法。

我想这样做的原因是因为大多数属性应该直接保存到数据库中,而一些属性,如密码,需要一些额外的处理。

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>'

有什么办法可以更改代码以使其正常工作吗?我需要一种方法来覆盖动态创建的方法。

4

3 回答 3

11

在 上定义方法superclass

class Model
  def self.attribute(name)
    superclass.send :define_method, name do
      self
    end
  end  
end
于 2010-01-03T13:50:54.630 回答
3

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
于 2010-01-03T13:51:44.613 回答
0

使用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
于 2018-12-05T11:58:23.050 回答