仅列出 ActiveRecord 子类方法
Posted
技术标签:
【中文标题】仅列出 ActiveRecord 子类方法【英文标题】:List only ActiveRecord subclass methods 【发布时间】:2012-02-26 21:43:15 【问题描述】:给定以下 ActiveRecord 模型:
class User < ActiveRecord::Base
has_many :games
def name
"Joe"
end
def city
"Chicago"
end
end
我想检索我直接添加到 User 类的方法列表(而不是通过扩展 ActiveRecord 和/或添加关联添加的方法)。示例输出:
["name","city"]
调用 User.instance_methods(false) 返回 ActiveRecord 添加的方法:
["validate_associated_records_for_games", "games", "game_ids", "games=", "game_ids=", "after_create_or_update_associated_records_for_games", "before_save_associated_records_for_games"]
连同来自数据库列的任何模型属性。我想排除这些,只获取子类上的自定义方法。
我的目的是方法跟踪:我想跟踪我的自定义方法,同时排除 ActiveRecord 添加的方法。
有什么想法吗?
【问题讨论】:
你用的是什么版本的rails? 我正在使用 Rails 2.2.2 进行测试,但我愿意接受更新版本的解决方案。 在 Rails 3.2 中,属性访问器、关联访问器以及可能的验证内容都在您的模型中包含的方法中定义,这使您尝试做的事情更容易 【参考方案1】:User.instance_methods - ActiveRecord::Base.instance_methods #=> [:name,:city]
更新:
这些方法的顺序很重要
class User < ActiveRecord::Base
def self.my_own_methods
self.instance_methods - @@im
end
has_many :games
@@im = self.instance_methods
def name
"Joe"
end
def city
"Chicago"
end
end
User.my_own_methods #=> [:name, :city]
这个已经测试过了
【讨论】:
这不起作用,因为AR自动生成的方法(例如DB列的方法)不会在ActiveRecord::Base.instance_methods
中。
是的 - 这将返回 ActiveRecord 添加到 User 类的方法。例如,您会看到像 :games=
这样的输出,这是我不想要的,但由于 has many :games
关联而被包含在内。
是的 - 这很有效,而且很简单。缺点是在所有 ActiveRecord 模型中实现它不会是 DRY 并且需要记录方法排序。【参考方案2】:
使用 method_added
钩子将方法名称添加到列表中,并使用猴子补丁 Active Record 以便 AR 添加的方法不会添加到该列表中。
如果您不想打开 AR 并开始四处寻找,您还可以定义一个“类宏”,它定义一个方法并将其添加到列表中。对于您自己的自定义方法,请使用类宏而不是 def
。
如果你不熟悉我所说的“类宏”,它只是一个这样的方法:
class Class
def mydef(name,&block)
(@methods || []) << name
define_method(name,&block)
end
end
使用mydef
之类的东西而不是def
来定义方法绝对是丑陋的,但它无需任何猴子补丁就可以解决问题。
【讨论】:
澄清一下,“类宏”是Class
上的一个实例方法,您可以从class
块中调用它来定义方法等。attr_accessor
是另一个示例。跨度>
方法的参数呢?
如果传递给define_method
的块接受参数,生成的方法也会接受参数。
是的 - 这会起作用。就像你说的,我需要跨模型更改我的方法定义。不过我喜欢这个方向:我已经重写了 ActiveRecord::Base 的 extend
方法来添加对子类的 method_added
调用。它检查第一个调用者的文件名是否与子类匹配。如果是这样,它将方法名称添加到数组中。这并不完美,但它确实抓住了模型文件中定义的所有方法。
好主意,我喜欢!如果此答案可以帮助您解决问题,我们将不胜感激。如果您可以分享可能对未来读者有用的代码,您可以编辑这篇文章以添加它(我会批准编辑)。以上是关于仅列出 ActiveRecord 子类方法的主要内容,如果未能解决你的问题,请参考以下文章