Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get a collection of all the Models in your Rails app?

People also ask

What are .includes in rails?

Making queries ⚡️ with :includes Rails provides an ActiveRecord method called :includes which loads associated records in advance and limits the number of SQL queries made to the database. This technique is known as "eager loading" and in many cases will improve performance by a significant amount.

What is a model in a Rails application?

A model is a Ruby class that is used to represent data. Additionally, models can interact with the application's database through a feature of Rails called Active Record.

How do I get rails console?

Go to your browser and open http://localhost:3000, you will see a basic Rails app running. You can also use the alias "s" to start the server: bin/rails s . The server can be run on a different port using the -p option. The default development environment can be changed using -e .

What is model in Ruby on Rails?

A Rails Model is a Ruby class that can add database records (think of whole rows in an Excel table), find particular data you're looking for, update that data, or remove data. These common operations are referred to by the acronym CRUD--Create, Remove, Update, Destroy.


The whole answer for Rails 3, 4 and 5 is:

If cache_classes is off (by default it's off in development, but on in production):

Rails.application.eager_load!

Then:

ActiveRecord::Base.descendants

This makes sure all models in your application, regardless of where they are, are loaded, and any gems you are using which provide models are also loaded.

This should also work on classes that inherit from ActiveRecord::Base, like ApplicationRecord in Rails 5, and return only that subtree of descendants:

ApplicationRecord.descendants

If you'd like to know more about how this is done, check out ActiveSupport::DescendantsTracker.


Just in case anyone stumbles on this one, I've got another solution, not relying on dir reading or extending the Class class...

ActiveRecord::Base.send :subclasses

This will return an array of classes. So you can then do

ActiveRecord::Base.send(:subclasses).map(&:name)

EDIT: Look at the comments and other answers. There are smarter answers than this one! Or try to improve this one as community wiki.

Models do not register themselves to a master object, so no, Rails does not have the list of models.

But you could still look in the content of the models directory of your application...

Dir.foreach("#{RAILS_ROOT}/app/models") do |model_path|
  # ...
end

EDIT: Another (wild) idea would be to use Ruby reflection to search for every classes that extends ActiveRecord::Base. Don't know how you can list all the classes though...

EDIT: Just for fun, I found a way to list all classes

Module.constants.select { |c| (eval c).is_a? Class }

EDIT: Finally succeeded in listing all models without looking at directories

Module.constants.select do |constant_name|
  constant = eval constant_name
  if not constant.nil? and constant.is_a? Class and constant.superclass == ActiveRecord::Base
    constant
  end
end

If you want to handle derived class too, then you will need to test the whole superclass chain. I did it by adding a method to the Class class:

class Class
  def extend?(klass)
    not superclass.nil? and ( superclass == klass or superclass.extend? klass )
  end
end

def models 
  Module.constants.select do |constant_name|
    constant = eval constant_name
    if not constant.nil? and constant.is_a? Class and constant.extend? ActiveRecord::Base
    constant
    end
  end
end

ActiveRecord::Base.connection.tables.map do |model|
  model.capitalize.singularize.camelize
end

will return

["Article", "MenuItem", "Post", "ZebraStripePerson"]

Additional information If you want to call a method on the object name without model:string unknown method or variable errors use this

model.classify.constantize.attribute_names

For Rails5 models are now subclasses of ApplicationRecord so to get list of all models in your app you do:

ApplicationRecord.descendants.collect { |type| type.name }

Or shorter:

ApplicationRecord.descendants.collect(&:name)

If you are in dev mode, you will need to eager load models before:

Rails.application.eager_load!

I looked for ways to do this and ended up choosing this way:

in the controller:
    @data_tables = ActiveRecord::Base.connection.tables

in the view:
  <% @data_tables.each do |dt|  %>
  <br>
  <%= dt %>
  <% end %>
  <br>

source: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project


I think @hnovick's solution is a cool one if you dont have table-less models. This solution would work in development mode as well

My approach is subtly different though -

ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact

classify is well supposed to give you the name of the class from a string properly. safe_constantize ensures that you can turn it into a class safely without throwing an exception. This is needed in case you have database tables which are not models. compact so that any nils in the enumeration are removed.