【问题标题】:Get all models having implemented a certain method获取所有实现了某个方法的模型
【发布时间】:2010-02-06 16:07:44
【问题描述】:

我有许多使用标准 rails 模型生成器创建的模型。 然后一些模型得到了一个名为 foo() 的方法。

有没有一种简单的方法可以计算出实现了 foo() 方法的生成模型的所有类名?

我的意思是从程序上,从 Rails 控制器,而不是从控制台获取源代码。

【问题讨论】:

    标签: ruby-on-rails object methods


    【解决方案1】:

    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 也触发了常规的依赖加载魔法。

    希望这有助于揭开某些事情的神秘面纱。 :)

    【讨论】:

      猜你喜欢
      • 2011-04-30
      • 2020-09-03
      • 2012-09-06
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      相关资源
      最近更新 更多