【发布时间】:2010-02-06 16:07:44
【问题描述】:
我有许多使用标准 rails 模型生成器创建的模型。 然后一些模型得到了一个名为 foo() 的方法。
有没有一种简单的方法可以计算出实现了 foo() 方法的生成模型的所有类名?
我的意思是从程序上,从 Rails 控制器,而不是从控制台获取源代码。
【问题讨论】:
标签: ruby-on-rails object methods
我有许多使用标准 rails 模型生成器创建的模型。 然后一些模型得到了一个名为 foo() 的方法。
有没有一种简单的方法可以计算出实现了 foo() 方法的生成模型的所有类名?
我的意思是从程序上,从 Rails 控制器,而不是从控制台获取源代码。
【问题讨论】:
标签: ruby-on-rails object methods
Rails 不会为您的模型保留索引,因此您只需遍历您的 app/models 目录即可。
这是一个例子:
# Open the model directory
models_dir = Dir.open("#{RAILS_ROOT}/app/models")
# Walk directory entries
models = models_dir.collect do |filename|
# Get the name without extension.
# (And skip anything that isn't a Ruby file.)
next if not filename =~ /^(.+)\.rb$/
basename = $~[1]
# Now, get the model class
klass = basename.camelize.constantize
# And return it, if it implements our method
klass if klass.method_defined? :foo
end
# Remove nils
models.compact!
Rails 会在第一次被引用时懒惰地加载您的模型和控制器。这是使用 Ruby 的 const_missing 方法完成的,您可以在 active_support/dependencies.rb 中看到 ActiveSupport 中发生的所有魔法。
要详细说明上面发生的事情,您还需要知道类名和文件名是相互关联的。 Rails 期望ThingyBob 模型存在于thingy_bob.rb 中。在这两个名称之间进行转换的方法是使用字符串方法camelize。 (相反的就是 underscore 方法。)这些字符串扩展也是 ActiveSupport 的一部分。
最后,使用 ActiveSupport 方法constantize,它也是一个字符串扩展,我们将字符串作为常量取消引用。所以基本上"ThingyBob".constantize和写ThingyBob是一样的;我们只需要返回 ThingyBob 类即可。在上面的例子中,constantize 也触发了常规的依赖加载魔法。
希望这有助于揭开某些事情的神秘面纱。 :)
【讨论】: