如何遍历我的rails应用程序中的所有模型?

时间:2010-05-01 23:11:00

标签: ruby-on-rails metaprogramming models

我希望能够迭代并检查我的rails应用程序中的所有模型。在伪代码中,它看起来像:

rails_env.models.each do |model|  
  associations = model.reflect_on_all_associations(:has_many)  
  ... do some stuff  
end

我的问题是如何检查我的rails应用程序以获取模型的集合(rails_env.models)?

5 个答案:

答案 0 :(得分:13)

与nathanvda的响应类似,使用camelize而不是capitalize来支持带下划线的模型文件,并使用String#constantize而不是Kernel.const_get。

此外,如果您在模型文件夹中保留非主动记录模型(例如,用于合并搜索逻辑的搜索类),您将需要检查该类是否为活动记录模型。

Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|
  klass = File.basename(filename, '.rb').camelize.constantize
  next unless klass.ancestors.include?(ActiveRecord::Base)
  next if klass.abstract_class?
  # do something with klass
end

答案 1 :(得分:2)

迭代`$ RAILS_ROOT \ app \ models'中的所有文件?

例如

def find_all_models
  # iterate over all files in folder
  folder = File.join(RAILS_ROOT, "app", "models")      
  Dir[File.join(folder, "*")].each do |filename|
    # remove .rb
    model_name = File.basename(filename).sub(/.rb$/, '').capitalize
    model = Kernel.const_get(model_name)
    # .. do something with your model :)
  end
end

这有帮助吗?

答案 2 :(得分:1)

Rails Admin使用此代码(请参阅https://github.com/sferik/rails_admin/blob/master/lib/rails_admin/config.rb,方法alive_models):

([Rails.application] + Rails::Engine.subclasses.collect(&:instance)).flat_map do |app|
          (app.paths['app/models'].to_a + app.config.autoload_paths).collect do |load_path|
            Dir.glob(app.root.join(load_path)).collect do |load_dir|
              Dir.glob(load_dir + '/**/*.rb').collect do |filename|
                # app/models/module/class.rb => module/class.rb => module/class => Module::Class
                lchomp(filename, "#{app.root.join(load_dir)}/").chomp('.rb').camelize
              end
            end
          end
        end.flatten.reject { |m| m.starts_with?('Concerns::') }

其优点是它可以在关联的引擎中加载模型,而不仅仅是在当前的应用程序中。

答案 3 :(得分:1)

我尝试在Rails 5下实现上述解决方案,但它们并没有完全奏效。这是一个解决方案,它找到所有以“page_”开头的模型(或任何其他前缀;只需指定):

def self.page_models(prefix = "page")
    models = []
    folder = File.join(Rails.root, "app", "models")
    Dir[File.join(folder, "*")].each do |filename|
     if filename =~ /models\/#{prefix}/
       klass = File.basename(filename, '.rb').camelize.constantize
       models << klass
     end
    end
    return models
end

答案 4 :(得分:1)

如果您只在现代Rails应用程序中查看ApplicationRecord模型,则可以使用

ApplicationRecord.descendants

您可以在此处查看:http://apidock.com/rails/Class/descendants