Is there a way to get a collection of all the Models in your Rails app?
Is there a way that you can get a collection of all of the Models in your Rails app?
Basically, can I do the likes of: -
Models.each do |model|
puts model.class.name
end
ruby-on-rails collections model
add a comment |
Is there a way that you can get a collection of all of the Models in your Rails app?
Basically, can I do the likes of: -
Models.each do |model|
puts model.class.name
end
ruby-on-rails collections model
1
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06
add a comment |
Is there a way that you can get a collection of all of the Models in your Rails app?
Basically, can I do the likes of: -
Models.each do |model|
puts model.class.name
end
ruby-on-rails collections model
Is there a way that you can get a collection of all of the Models in your Rails app?
Basically, can I do the likes of: -
Models.each do |model|
puts model.class.name
end
ruby-on-rails collections model
ruby-on-rails collections model
edited Apr 16 '15 at 23:08
royhowie
8,906133758
8,906133758
asked Feb 5 '09 at 16:10
mr_urf
1,51031928
1,51031928
1
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06
add a comment |
1
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06
1
1
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06
add a comment |
27 Answers
27
active
oldest
votes
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
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
RAILS_ROOT
is no longer available in Rails 3. Instead, useDir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
Actually, the models do register themselves as descendants ofActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.
– sj26
Aug 20 '12 at 9:52
|
show 8 more comments
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.
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on:environment
for theeager_load!
to work.
– Jo Liss
Aug 17 '12 at 21:06
1
Or, as a slightly faster alternative toRails.application.eager_load!
, you can just load the models:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob allRails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.
– sj26
Nov 30 '12 at 3:46
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
|
show 13 more comments
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)
8
why don't you useActiveRecord::Base.subclasses
but have to usesend
? Also, it seems like you have to "touch" the model before it will show up, for examplec = Category.new
and it will show up. Otherwise, it won't.
– 太極者無極而生
Sep 6 '10 at 15:12
52
In Rails 3, this has been changed toActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models beforeActiveRecord::Base.descendants
will list them.
– nfm
Jul 3 '11 at 1:18
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
|
show 4 more comments
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
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better thanActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.
– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to.classify
.
– Maxim Dobryakov
Apr 23 '17 at 18:46
add a comment |
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
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
A few useful methods:ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.
– Andrei
Feb 18 '11 at 11:47
2
Adapting @Andrei's a bit:model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
add a comment |
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.
3
That's awesome @Aditya Sanghi. I didn't know aboutsafe_constantize
.
– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
add a comment |
If you want just the Class names:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
Rails.application.eager_load!
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
callingmap
withputs
? I don't get the point should beActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
add a comment |
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 take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
add a comment |
This seems to work for me:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
add a comment |
On one line: Dir['app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
add a comment |
ActiveRecord::Base.connection.tables
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
add a comment |
In just one line:
ActiveRecord::Base.subclasses.map(&:name)
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
It's probably needsRails.application.eager_load!
before execution in development mode.
– denis.peplin
Sep 23 '15 at 5:43
add a comment |
I can't comment yet, but I think sj26 answer should be the top answer. Just a hint:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
add a comment |
This works for Rails 3.2.18
Rails.application.eager_load!
def all_models
models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
m.chomp('.rb').camelize.split("::").last
end
end
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
add a comment |
To avoid pre-load all Rails, you can do this:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
require_dependency(f) is the same that Rails.application.eager_load!
uses. This should avoid already required file errors.
Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants
add a comment |
Yes there are many ways you can find all model names but what I did in my gem model_info is , it will give you all the models even included in the gems.
array=, @model_array=
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
then simply print this
@model_array
add a comment |
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
add a comment |
Here's a solution that has been vetted with a complex Rails app (the one powering Square)
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
It takes the best parts of the answers in this thread and combines them in the simplest and most thorough solution. This handle cases where your models are in subdirectories, use set_table_name etc.
add a comment |
Just came across this one, as I need to print all models with their attributes(built on @Aditya Sanghi's comment):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "nn"+model.name; model.new.attributes.each{|a,b| print "n#{a}"}}
add a comment |
This worked for me. Special thanks to all the posts above. This should return a collection of all your models.
models =
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(//models//)
models.push temp.last.gsub(/.rb$/, '').camelize.constantize rescue nil
end
add a comment |
The Rails
implements the method descendants
, but models not necessarily ever inherits from ActiveRecord::Base
, for example, the class that includes the module ActiveModel::Model
will have the same behavior as a model, just doesn't will be linked to a table.
So complementing what says the colleagues above, the slightest effort would do this:
Monkey Patch of class Class
of the Ruby:
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
and the method models
, including ancestors, as this:
The method Module.constants
returns (superficially) a collection of symbols
, instead of constants, so, the method Array#select
can be substituted like this monkey patch of the Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant "#{constant}" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=, &block
trail = self.to_s
collected =
recursivityQueue =
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
Monkey patch of String
.
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
And, finally, the models method
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
add a comment |
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
add a comment |
I've tried so many of these answers unsuccessfully in Rails 4 (wow they changed a thing or two for god sakes) I decided to add my own. The ones that called ActiveRecord::Base.connection and pulled the table names worked but didn't get the result I wanted because I've hidden some models (in a folder inside of app/models/) that I didn't want to delete:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
I put that in an initializer and can call it from anywhere. Prevents unnecessary mouse-usage.
add a comment |
can check this
@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}
add a comment |
Assuming all models are in app/models and you have grep & awk on your server (majority of the cases),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("n")
It it faster than Rails.application.eager_load!
or looping through each file with Dir
.
EDIT:
The disadvantage of this method is that it misses models that indirectly inherit from ActiveRecord (e.g. FictionalBook < Book
). The surest way is Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, even though it's kinda slow.
add a comment |
I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.
Let say you have a column public_uid
that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)
Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
you can now run rake di:public_uids:generate
add a comment |
Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
next unless model_path.match(/.rb$/)
model_class = model_path.gsub(/.rb$/, '').classify.constantize
puts model_class
end
This will give to you all the model classes you have on your project.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f516579%2fis-there-a-way-to-get-a-collection-of-all-the-models-in-your-rails-app%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
27 Answers
27
active
oldest
votes
27 Answers
27
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
RAILS_ROOT
is no longer available in Rails 3. Instead, useDir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
Actually, the models do register themselves as descendants ofActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.
– sj26
Aug 20 '12 at 9:52
|
show 8 more comments
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
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
RAILS_ROOT
is no longer available in Rails 3. Instead, useDir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
Actually, the models do register themselves as descendants ofActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.
– sj26
Aug 20 '12 at 9:52
|
show 8 more comments
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
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
edited Jan 17 '14 at 16:03
community wiki
6 revs, 2 users 98%
Vincent Robert
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
RAILS_ROOT
is no longer available in Rails 3. Instead, useDir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
Actually, the models do register themselves as descendants ofActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.
– sj26
Aug 20 '12 at 9:52
|
show 8 more comments
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
RAILS_ROOT
is no longer available in Rails 3. Instead, useDir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
Actually, the models do register themselves as descendants ofActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.
– sj26
Aug 20 '12 at 9:52
5
5
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
FYI, I timed both methods just for fun. Looking up the directories is an order of magnitude faster than searching though the classes. That was probably obvious, but now you know :)
– Edward Anderson
Jun 12 '10 at 14:25
9
9
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
Also, it's important to note that searching for models via the constants methods will not include anything that hasn't been referenced since the app started, since it only loads the models on demand.
– Edward Anderson
Jun 12 '10 at 14:27
4
4
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
I prefer 'Kernel.const_get constant_name' to 'eval constant_name'.
– Jeremy Weathers
Nov 27 '10 at 18:48
3
3
RAILS_ROOT
is no longer available in Rails 3. Instead, use Dir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
RAILS_ROOT
is no longer available in Rails 3. Instead, use Dir.glob(Rails.root.join('app/models/*'))
– fanaugen
May 16 '12 at 10:50
1
1
Actually, the models do register themselves as descendants of
ActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.– sj26
Aug 20 '12 at 9:52
Actually, the models do register themselves as descendants of
ActiveRecord::Base
now, so if you eager load all models then you can iterate them easily—see my answer below.– sj26
Aug 20 '12 at 9:52
|
show 8 more comments
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.
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on:environment
for theeager_load!
to work.
– Jo Liss
Aug 17 '12 at 21:06
1
Or, as a slightly faster alternative toRails.application.eager_load!
, you can just load the models:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob allRails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.
– sj26
Nov 30 '12 at 3:46
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
|
show 13 more comments
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.
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on:environment
for theeager_load!
to work.
– Jo Liss
Aug 17 '12 at 21:06
1
Or, as a slightly faster alternative toRails.application.eager_load!
, you can just load the models:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob allRails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.
– sj26
Nov 30 '12 at 3:46
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
|
show 13 more comments
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.
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.
edited Nov 28 '16 at 22:54
answered May 23 '12 at 2:52
sj26
5,39822123
5,39822123
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on:environment
for theeager_load!
to work.
– Jo Liss
Aug 17 '12 at 21:06
1
Or, as a slightly faster alternative toRails.application.eager_load!
, you can just load the models:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob allRails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.
– sj26
Nov 30 '12 at 3:46
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
|
show 13 more comments
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on:environment
for theeager_load!
to work.
– Jo Liss
Aug 17 '12 at 21:06
1
Or, as a slightly faster alternative toRails.application.eager_load!
, you can just load the models:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob allRails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.
– sj26
Nov 30 '12 at 3:46
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
31
31
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on
:environment
for the eager_load!
to work.– Jo Liss
Aug 17 '12 at 21:06
Awesome! This should be the accepted answer. For anybody using this in a rake task: Make your task depend on
:environment
for the eager_load!
to work.– Jo Liss
Aug 17 '12 at 21:06
1
1
Or, as a slightly faster alternative to
Rails.application.eager_load!
, you can just load the models: Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
Or, as a slightly faster alternative to
Rails.application.eager_load!
, you can just load the models: Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
– Ajedi32
Aug 29 '12 at 18:54
5
5
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob all
Rails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.– sj26
Nov 30 '12 at 3:46
@Ajedi32 that is not complete, models can be defined outside those directories, especially when using engines with models. Slightly better, at least glob all
Rails.paths["app/models"].existent
directories. Eager loading the whole application is a more complete answer and will make sure there is absolutely nowhere left for models to be defined.– sj26
Nov 30 '12 at 3:46
2
2
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
I got what sj26 means but maybe there is a little mistake: as far as I know in development environment cache_classes is off (false) that's why you need to manually eager load the application to access all models. explained here
– masciugo
Oct 17 '13 at 9:04
3
3
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:
Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
@Ajedi32 again, not the complete answer. If you want to eager load only models then try:
Rails.application.paths["app/models"].eager_load!
– sj26
Oct 29 '13 at 6:19
|
show 13 more comments
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)
8
why don't you useActiveRecord::Base.subclasses
but have to usesend
? Also, it seems like you have to "touch" the model before it will show up, for examplec = Category.new
and it will show up. Otherwise, it won't.
– 太極者無極而生
Sep 6 '10 at 15:12
52
In Rails 3, this has been changed toActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models beforeActiveRecord::Base.descendants
will list them.
– nfm
Jul 3 '11 at 1:18
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
|
show 4 more comments
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)
8
why don't you useActiveRecord::Base.subclasses
but have to usesend
? Also, it seems like you have to "touch" the model before it will show up, for examplec = Category.new
and it will show up. Otherwise, it won't.
– 太極者無極而生
Sep 6 '10 at 15:12
52
In Rails 3, this has been changed toActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models beforeActiveRecord::Base.descendants
will list them.
– nfm
Jul 3 '11 at 1:18
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
|
show 4 more comments
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)
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)
edited Nov 14 '13 at 22:17
boulder_ruby
26.3k65873
26.3k65873
answered Jan 12 '10 at 10:50
kikito
38.8k23125177
38.8k23125177
8
why don't you useActiveRecord::Base.subclasses
but have to usesend
? Also, it seems like you have to "touch" the model before it will show up, for examplec = Category.new
and it will show up. Otherwise, it won't.
– 太極者無極而生
Sep 6 '10 at 15:12
52
In Rails 3, this has been changed toActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models beforeActiveRecord::Base.descendants
will list them.
– nfm
Jul 3 '11 at 1:18
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
|
show 4 more comments
8
why don't you useActiveRecord::Base.subclasses
but have to usesend
? Also, it seems like you have to "touch" the model before it will show up, for examplec = Category.new
and it will show up. Otherwise, it won't.
– 太極者無極而生
Sep 6 '10 at 15:12
52
In Rails 3, this has been changed toActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models beforeActiveRecord::Base.descendants
will list them.
– nfm
Jul 3 '11 at 1:18
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
8
8
why don't you use
ActiveRecord::Base.subclasses
but have to use send
? Also, it seems like you have to "touch" the model before it will show up, for example c = Category.new
and it will show up. Otherwise, it won't.– 太極者無極而生
Sep 6 '10 at 15:12
why don't you use
ActiveRecord::Base.subclasses
but have to use send
? Also, it seems like you have to "touch" the model before it will show up, for example c = Category.new
and it will show up. Otherwise, it won't.– 太極者無極而生
Sep 6 '10 at 15:12
52
52
In Rails 3, this has been changed to
ActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
In Rails 3, this has been changed to
ActiveRecord::Base.descendants
– Tobias Cohen
Feb 16 '11 at 4:19
3
3
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
You have to use "send" because the :subclasses member is protected.
– Kevin Rood
Apr 1 '11 at 18:53
10
10
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models before
ActiveRecord::Base.descendants
will list them.– nfm
Jul 3 '11 at 1:18
Thanks for the Rails 3 tip. For anyone else who comes along, you still need to "touch" the models before
ActiveRecord::Base.descendants
will list them.– nfm
Jul 3 '11 at 1:18
3
3
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
Technically in Rails 3 you have subclasses and descendants, they mean different things.
– sj26
May 17 '12 at 5:03
|
show 4 more comments
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
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better thanActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.
– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to.classify
.
– Maxim Dobryakov
Apr 23 '17 at 18:46
add a comment |
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
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better thanActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.
– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to.classify
.
– Maxim Dobryakov
Apr 23 '17 at 18:46
add a comment |
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
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
edited Jun 4 '15 at 0:45
Conor
319114
319114
answered Dec 8 '11 at 21:34
lightyrs
1,79321828
1,79321828
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better thanActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.
– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to.classify
.
– Maxim Dobryakov
Apr 23 '17 at 18:46
add a comment |
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better thanActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.
– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to.classify
.
– Maxim Dobryakov
Apr 23 '17 at 18:46
7
7
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Mar 29 '12 at 21:25
1
1
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
That's a great point; thanks.
– lightyrs
Mar 30 '12 at 1:15
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
This answer should be considered incorrect as it is feasible (and common in legacy setups) to configure the name of the table to be something other than pluralized name of the model. This answer gives the correct answer even when the setup deviates from the default configuration.
– lorefnon
May 22 '16 at 11:18
in some cases this works better than
ActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.– Tilo
Apr 13 '17 at 15:02
in some cases this works better than
ActiveRecord::Base.send :subclasses
- looking for the table names is a good idea. Automatically generating the model names might be problematic as lorefnon mentioned.– Tilo
Apr 13 '17 at 15:02
.capitalize.singularize.camelize
can be replaced to .classify
.– Maxim Dobryakov
Apr 23 '17 at 18:46
.capitalize.singularize.camelize
can be replaced to .classify
.– Maxim Dobryakov
Apr 23 '17 at 18:46
add a comment |
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
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
A few useful methods:ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.
– Andrei
Feb 18 '11 at 11:47
2
Adapting @Andrei's a bit:model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
add a comment |
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
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
A few useful methods:ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.
– Andrei
Feb 18 '11 at 11:47
2
Adapting @Andrei's a bit:model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
add a comment |
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 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
answered Jan 4 '11 at 20:30
jaime
808711
808711
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
A few useful methods:ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.
– Andrei
Feb 18 '11 at 11:47
2
Adapting @Andrei's a bit:model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
add a comment |
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
A few useful methods:ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.
– Andrei
Feb 18 '11 at 11:47
2
Adapting @Andrei's a bit:model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
1
1
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
This is the only way I can get ALL models, including models of Rails engines used in the app. Thanks for the tip!
– Andrei
Feb 18 '11 at 11:18
2
2
A few useful methods:
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.– Andrei
Feb 18 '11 at 11:47
A few useful methods:
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Some of the models may be not activated therefore you need to rescue it.– Andrei
Feb 18 '11 at 11:47
2
2
Adapting @Andrei's a bit:
model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
Adapting @Andrei's a bit:
model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
– Max Williams
Jun 17 '11 at 9:59
3
3
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
This will not work for Single Table Inheritance.
– Joseph Jaber
Nov 1 '11 at 21:51
add a comment |
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.
3
That's awesome @Aditya Sanghi. I didn't know aboutsafe_constantize
.
– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
add a comment |
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.
3
That's awesome @Aditya Sanghi. I didn't know aboutsafe_constantize
.
– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
add a comment |
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.
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.
answered May 21 '12 at 7:27
Aditya Sanghi
12.2k23750
12.2k23750
3
That's awesome @Aditya Sanghi. I didn't know aboutsafe_constantize
.
– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
add a comment |
3
That's awesome @Aditya Sanghi. I didn't know aboutsafe_constantize
.
– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
3
3
That's awesome @Aditya Sanghi. I didn't know about
safe_constantize
.– lightyrs
Sep 18 '12 at 2:28
That's awesome @Aditya Sanghi. I didn't know about
safe_constantize
.– lightyrs
Sep 18 '12 at 2:28
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
For rails 2.3.x, use: ActiveRecord::Base.connection.tables.map{|x|x.classify.constantize rescue nil}.compact
– iheggie
Oct 27 '14 at 1:36
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
@iheggie It is generally better to post that as a separate answer than editing it into the existing post.
– Pokechu22
Oct 27 '14 at 1:52
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
thanks, I found you answer best suited for me #adiya
– illusionist
Apr 10 '15 at 5:30
add a comment |
If you want just the Class names:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
Rails.application.eager_load!
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
callingmap
withputs
? I don't get the point should beActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
add a comment |
If you want just the Class names:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
Rails.application.eager_load!
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
callingmap
withputs
? I don't get the point should beActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
add a comment |
If you want just the Class names:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
Rails.application.eager_load!
If you want just the Class names:
ActiveRecord::Base.descendants.map {|f| puts f}
Just run it in Rails console, nothing more. Good luck!
EDIT: @sj26 is right, you need to run this first before you can call descendants:
Rails.application.eager_load!
edited Jul 12 '14 at 15:11
answered Jan 5 '14 at 5:28
Jordan Michael Rushing
406510
406510
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
callingmap
withputs
? I don't get the point should beActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
add a comment |
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
callingmap
withputs
? I don't get the point should beActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
Just what I wanted. Thank!
– sunsations
Jun 19 '14 at 8:33
calling
map
with puts
? I don't get the point should be ActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
calling
map
with puts
? I don't get the point should be ActiveRecord::Base.descendants.map(&:model_name)
– Nuno Costa
Oct 12 '15 at 13:36
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
You can do it that way, but they'll be in a single array, instead of line by line, in a much easier to read format.
– Jordan Michael Rushing
Oct 12 '15 at 21:06
add a comment |
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 take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
add a comment |
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 take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
add a comment |
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!
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!
edited Jan 22 '17 at 6:52
answered Mar 29 '16 at 7:06
Nimir
4,19911630
4,19911630
I take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
add a comment |
I take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
I take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
I take it that this would require that classes are already loaded and would give incomplete results in development environment with autoloading enabled. I will not downvote but perhaps this should be mentioned in the answer.
– lorefnon
May 22 '16 at 11:14
fare enough, updating
– Nimir
May 22 '16 at 11:22
fare enough, updating
– Nimir
May 22 '16 at 11:22
add a comment |
This seems to work for me:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
add a comment |
This seems to work for me:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
add a comment |
This seems to work for me:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
This seems to work for me:
Dir.glob(RAILS_ROOT + '/app/models/*.rb').each { |file| require file }
@models = Object.subclasses_of(ActiveRecord::Base)
Rails only loads models when they are used, so the Dir.glob line "requires" all the files in the models directory.
Once you have the models in an array, you can do what you were thinking (e.g. in view code):
<% @models.each do |v| %>
<li><%= h v.to_s %></li>
<% end %>
answered Feb 6 '09 at 16:49
bhousel
35116
35116
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
add a comment |
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
Thanks bhousel. I originally went with this style of approach but ended up using the solution that Vincent posted above as it meant that I didn't have to "Modelize" the file name as well (i.e. strip out any _, capitalize! each word and then join them again).
– mr_urf
Feb 7 '09 at 14:03
with subdirectories:
...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
with subdirectories:
...'/app/models/**/*.rb'
– artemave
Mar 16 '11 at 10:30
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
Object.subclasses_of is deprecated after v2.3.8.
– David J.
Jul 25 '12 at 15:55
add a comment |
On one line: Dir['app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
add a comment |
On one line: Dir['app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
add a comment |
On one line: Dir['app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
On one line: Dir['app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
edited Jul 25 '12 at 21:06
meagar♦
177k29272288
177k29272288
answered Mar 11 '10 at 15:42
vjt
40948
40948
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
add a comment |
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
7
7
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
This one is nice since, in Rails 3, your models aren't auto-loaded by default, so many of the above methods won't return all possible models. My permutation also captures models in plugins and subdirectories:
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
– wbharding
Feb 25 '11 at 19:12
2
2
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding That's pretty nice, but it errors out when it tries to constantize the names of my rspec model tests. ;-)
– Ajedi32
Aug 29 '12 at 19:11
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
@wbharding nice solution but it breaks when you have namespaced models
– Marcus Mansur
Oct 4 '13 at 17:50
add a comment |
ActiveRecord::Base.connection.tables
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
add a comment |
ActiveRecord::Base.connection.tables
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
add a comment |
ActiveRecord::Base.connection.tables
ActiveRecord::Base.connection.tables
edited Jun 28 '14 at 3:26
zishe
7,962104890
7,962104890
answered Apr 16 '12 at 14:35
Mark Locklear
2,91712946
2,91712946
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
add a comment |
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
Also a nice followup is <table_name>.column_names to list all columns in the table. So for your user table you would execute User.column_names
– Mark Locklear
Aug 13 '12 at 12:35
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
This will get you all the tables though, not just the models, since some tables don't always have associated models.
– courtsimas
Apr 15 '13 at 23:20
1
1
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
this works for me in Rails 5.2
– xyz
Jun 8 at 2:45
add a comment |
In just one line:
ActiveRecord::Base.subclasses.map(&:name)
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
It's probably needsRails.application.eager_load!
before execution in development mode.
– denis.peplin
Sep 23 '15 at 5:43
add a comment |
In just one line:
ActiveRecord::Base.subclasses.map(&:name)
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
It's probably needsRails.application.eager_load!
before execution in development mode.
– denis.peplin
Sep 23 '15 at 5:43
add a comment |
In just one line:
ActiveRecord::Base.subclasses.map(&:name)
In just one line:
ActiveRecord::Base.subclasses.map(&:name)
answered Jul 19 '12 at 14:08
Adrian
4,06832328
4,06832328
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
It's probably needsRails.application.eager_load!
before execution in development mode.
– denis.peplin
Sep 23 '15 at 5:43
add a comment |
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
It's probably needsRails.application.eager_load!
before execution in development mode.
– denis.peplin
Sep 23 '15 at 5:43
2
2
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
That doesn't show all the models for me. Not sure why. It's a couple short, in fact.
– courtsimas
Apr 15 '13 at 23:20
1
1
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
worked for me. 'just a little late to answer thats all. give it time.
– boulder_ruby
Oct 17 '13 at 23:43
2
2
It's probably needs
Rails.application.eager_load!
before execution in development mode.– denis.peplin
Sep 23 '15 at 5:43
It's probably needs
Rails.application.eager_load!
before execution in development mode.– denis.peplin
Sep 23 '15 at 5:43
add a comment |
I can't comment yet, but I think sj26 answer should be the top answer. Just a hint:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
add a comment |
I can't comment yet, but I think sj26 answer should be the top answer. Just a hint:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
add a comment |
I can't comment yet, but I think sj26 answer should be the top answer. Just a hint:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
I can't comment yet, but I think sj26 answer should be the top answer. Just a hint:
Rails.application.eager_load! unless Rails.configuration.cache_classes
ActiveRecord::Base.descendants
edited May 23 '17 at 12:10
Community♦
11
11
answered Nov 13 '13 at 15:38
panteo
465410
465410
add a comment |
add a comment |
This works for Rails 3.2.18
Rails.application.eager_load!
def all_models
models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
m.chomp('.rb').camelize.split("::").last
end
end
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
add a comment |
This works for Rails 3.2.18
Rails.application.eager_load!
def all_models
models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
m.chomp('.rb').camelize.split("::").last
end
end
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
add a comment |
This works for Rails 3.2.18
Rails.application.eager_load!
def all_models
models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
m.chomp('.rb').camelize.split("::").last
end
end
This works for Rails 3.2.18
Rails.application.eager_load!
def all_models
models = Dir["#{Rails.root}/app/models/**/*.rb"].map do |m|
m.chomp('.rb').camelize.split("::").last
end
end
answered Jul 26 '14 at 22:34
ryan0
1,0041115
1,0041115
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
add a comment |
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
upvolt for that Rails.application.eager_load! idea
– equivalent8
May 28 '15 at 14:01
add a comment |
To avoid pre-load all Rails, you can do this:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
require_dependency(f) is the same that Rails.application.eager_load!
uses. This should avoid already required file errors.
Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants
add a comment |
To avoid pre-load all Rails, you can do this:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
require_dependency(f) is the same that Rails.application.eager_load!
uses. This should avoid already required file errors.
Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants
add a comment |
To avoid pre-load all Rails, you can do this:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
require_dependency(f) is the same that Rails.application.eager_load!
uses. This should avoid already required file errors.
Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants
To avoid pre-load all Rails, you can do this:
Dir.glob("#{Rails.root}/app/models/**/*.rb").each {|f| require_dependency(f) }
require_dependency(f) is the same that Rails.application.eager_load!
uses. This should avoid already required file errors.
Then you can use all kind of solutions to list AR models, like ActiveRecord::Base.descendants
answered Mar 28 '17 at 15:48
John Owen Chile
226138
226138
add a comment |
add a comment |
Yes there are many ways you can find all model names but what I did in my gem model_info is , it will give you all the models even included in the gems.
array=, @model_array=
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
then simply print this
@model_array
add a comment |
Yes there are many ways you can find all model names but what I did in my gem model_info is , it will give you all the models even included in the gems.
array=, @model_array=
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
then simply print this
@model_array
add a comment |
Yes there are many ways you can find all model names but what I did in my gem model_info is , it will give you all the models even included in the gems.
array=, @model_array=
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
then simply print this
@model_array
Yes there are many ways you can find all model names but what I did in my gem model_info is , it will give you all the models even included in the gems.
array=, @model_array=
Rails.application.eager_load!
array=ActiveRecord::Base.descendants.collect{|x| x.to_s if x.table_exists?}.compact
array.each do |x|
if x.split('::').last.split('_').first != "HABTM"
@model_array.push(x)
end
@model_array.delete('ActiveRecord::SchemaMigration')
end
then simply print this
@model_array
edited Jun 23 '17 at 11:28
answered Apr 28 '17 at 6:22
nitanshu verma
15518
15518
add a comment |
add a comment |
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
add a comment |
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
add a comment |
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
Module.constants.select { |c| (eval c).is_a?(Class) && (eval c) < ActiveRecord::Base }
answered Mar 27 '12 at 12:14
Naveed
9,21423455
9,21423455
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
add a comment |
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
throws TypeError: no implicit conversion of Symbol into String in the console.
– snowangel
Dec 16 '13 at 12:49
add a comment |
Here's a solution that has been vetted with a complex Rails app (the one powering Square)
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
It takes the best parts of the answers in this thread and combines them in the simplest and most thorough solution. This handle cases where your models are in subdirectories, use set_table_name etc.
add a comment |
Here's a solution that has been vetted with a complex Rails app (the one powering Square)
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
It takes the best parts of the answers in this thread and combines them in the simplest and most thorough solution. This handle cases where your models are in subdirectories, use set_table_name etc.
add a comment |
Here's a solution that has been vetted with a complex Rails app (the one powering Square)
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
It takes the best parts of the answers in this thread and combines them in the simplest and most thorough solution. This handle cases where your models are in subdirectories, use set_table_name etc.
Here's a solution that has been vetted with a complex Rails app (the one powering Square)
def all_models
# must eager load all the classes...
Dir.glob("#{RAILS_ROOT}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
# simply return them
ActiveRecord::Base.send(:subclasses)
end
It takes the best parts of the answers in this thread and combines them in the simplest and most thorough solution. This handle cases where your models are in subdirectories, use set_table_name etc.
answered Jun 10 '13 at 12:41
Pascal-Louis Perez
14112
14112
add a comment |
add a comment |
Just came across this one, as I need to print all models with their attributes(built on @Aditya Sanghi's comment):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "nn"+model.name; model.new.attributes.each{|a,b| print "n#{a}"}}
add a comment |
Just came across this one, as I need to print all models with their attributes(built on @Aditya Sanghi's comment):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "nn"+model.name; model.new.attributes.each{|a,b| print "n#{a}"}}
add a comment |
Just came across this one, as I need to print all models with their attributes(built on @Aditya Sanghi's comment):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "nn"+model.name; model.new.attributes.each{|a,b| print "n#{a}"}}
Just came across this one, as I need to print all models with their attributes(built on @Aditya Sanghi's comment):
ActiveRecord::Base.connection.tables.map{|x|x.classify.safe_constantize}.compact.each{ |model| print "nn"+model.name; model.new.attributes.each{|a,b| print "n#{a}"}}
answered Oct 23 '13 at 6:24
gouravtiwari21
18919
18919
add a comment |
add a comment |
This worked for me. Special thanks to all the posts above. This should return a collection of all your models.
models =
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(//models//)
models.push temp.last.gsub(/.rb$/, '').camelize.constantize rescue nil
end
add a comment |
This worked for me. Special thanks to all the posts above. This should return a collection of all your models.
models =
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(//models//)
models.push temp.last.gsub(/.rb$/, '').camelize.constantize rescue nil
end
add a comment |
This worked for me. Special thanks to all the posts above. This should return a collection of all your models.
models =
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(//models//)
models.push temp.last.gsub(/.rb$/, '').camelize.constantize rescue nil
end
This worked for me. Special thanks to all the posts above. This should return a collection of all your models.
models =
Dir.glob("#{Rails.root}/app/models/**/*.rb") do |model_path|
temp = model_path.split(//models//)
models.push temp.last.gsub(/.rb$/, '').camelize.constantize rescue nil
end
answered Nov 13 '13 at 23:02
Kevin
1968
1968
add a comment |
add a comment |
The Rails
implements the method descendants
, but models not necessarily ever inherits from ActiveRecord::Base
, for example, the class that includes the module ActiveModel::Model
will have the same behavior as a model, just doesn't will be linked to a table.
So complementing what says the colleagues above, the slightest effort would do this:
Monkey Patch of class Class
of the Ruby:
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
and the method models
, including ancestors, as this:
The method Module.constants
returns (superficially) a collection of symbols
, instead of constants, so, the method Array#select
can be substituted like this monkey patch of the Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant "#{constant}" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=, &block
trail = self.to_s
collected =
recursivityQueue =
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
Monkey patch of String
.
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
And, finally, the models method
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
add a comment |
The Rails
implements the method descendants
, but models not necessarily ever inherits from ActiveRecord::Base
, for example, the class that includes the module ActiveModel::Model
will have the same behavior as a model, just doesn't will be linked to a table.
So complementing what says the colleagues above, the slightest effort would do this:
Monkey Patch of class Class
of the Ruby:
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
and the method models
, including ancestors, as this:
The method Module.constants
returns (superficially) a collection of symbols
, instead of constants, so, the method Array#select
can be substituted like this monkey patch of the Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant "#{constant}" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=, &block
trail = self.to_s
collected =
recursivityQueue =
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
Monkey patch of String
.
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
And, finally, the models method
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
add a comment |
The Rails
implements the method descendants
, but models not necessarily ever inherits from ActiveRecord::Base
, for example, the class that includes the module ActiveModel::Model
will have the same behavior as a model, just doesn't will be linked to a table.
So complementing what says the colleagues above, the slightest effort would do this:
Monkey Patch of class Class
of the Ruby:
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
and the method models
, including ancestors, as this:
The method Module.constants
returns (superficially) a collection of symbols
, instead of constants, so, the method Array#select
can be substituted like this monkey patch of the Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant "#{constant}" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=, &block
trail = self.to_s
collected =
recursivityQueue =
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
Monkey patch of String
.
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
And, finally, the models method
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
The Rails
implements the method descendants
, but models not necessarily ever inherits from ActiveRecord::Base
, for example, the class that includes the module ActiveModel::Model
will have the same behavior as a model, just doesn't will be linked to a table.
So complementing what says the colleagues above, the slightest effort would do this:
Monkey Patch of class Class
of the Ruby:
class Class
def extends? constant
ancestors.include?(constant) if constant != self
end
end
and the method models
, including ancestors, as this:
The method Module.constants
returns (superficially) a collection of symbols
, instead of constants, so, the method Array#select
can be substituted like this monkey patch of the Module
:
class Module
def demodulize
splitted_trail = self.to_s.split("::")
constant = splitted_trail.last
const_get(constant) if defines?(constant)
end
private :demodulize
def defines? constant, verbose=false
splitted_trail = constant.split("::")
trail_name = splitted_trail.first
begin
trail = const_get(trail_name) if Object.send(:const_defined?, trail_name)
splitted_trail.slice(1, splitted_trail.length - 1).each do |constant_name|
trail = trail.send(:const_defined?, constant_name) ? trail.const_get(constant_name) : nil
end
true if trail
rescue Exception => e
$stderr.puts "Exception recovered when trying to check if the constant "#{constant}" is defined: #{e}" if verbose
end unless constant.empty?
end
def has_constants?
true if constants.any?
end
def nestings counted=, &block
trail = self.to_s
collected =
recursivityQueue =
constants.each do |const_name|
const_name = const_name.to_s
const_for_try = "#{trail}::#{const_name}"
constant = const_for_try.constantize
begin
constant_sym = constant.to_s.to_sym
if constant && !counted.include?(constant_sym)
counted << constant_sym
if (constant.is_a?(Module) || constant.is_a?(Class))
value = block_given? ? block.call(constant) : constant
collected << value if value
recursivityQueue.push({
constant: constant,
counted: counted,
block: block
}) if constant.has_constants?
end
end
rescue Exception
end
end
recursivityQueue.each do |data|
collected.concat data[:constant].nestings(data[:counted], &data[:block])
end
collected
end
end
Monkey patch of String
.
class String
def constantize
if Module.defines?(self)
Module.const_get self
else
demodulized = self.split("::").last
Module.const_get(demodulized) if Module.defines?(demodulized)
end
end
end
And, finally, the models method
def models
# preload only models
application.config.eager_load_paths = model_eager_load_paths
application.eager_load!
models = Module.nestings do |const|
const if const.is_a?(Class) && const != ActiveRecord::SchemaMigration && (const.extends?(ActiveRecord::Base) || const.include?(ActiveModel::Model))
end
end
private
def application
::Rails.application
end
def model_eager_load_paths
eager_load_paths = application.config.eager_load_paths.collect do |eager_load_path|
model_paths = application.config.paths["app/models"].collect do |model_path|
eager_load_path if Regexp.new("(#{model_path})$").match(eager_load_path)
end
end.flatten.compact
end
edited Nov 12 '16 at 21:17
answered Oct 16 '16 at 21:21
rplaurindo
605716
605716
add a comment |
add a comment |
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
add a comment |
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
add a comment |
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
def load_models_in_development
if Rails.env == "development"
load_models_for(Rails.root)
Rails.application.railties.engines.each do |r|
load_models_for(r.root)
end
end
end
def load_models_for(root)
Dir.glob("#{root}/app/models/**/*.rb") do |model_path|
begin
require model_path
rescue
# ignore
end
end
end
answered Aug 22 '13 at 5:29
Abdul
1
1
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
add a comment |
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
Can you provide some explanation of the code as well..?
– NREZ
Aug 22 '13 at 5:49
add a comment |
I've tried so many of these answers unsuccessfully in Rails 4 (wow they changed a thing or two for god sakes) I decided to add my own. The ones that called ActiveRecord::Base.connection and pulled the table names worked but didn't get the result I wanted because I've hidden some models (in a folder inside of app/models/) that I didn't want to delete:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
I put that in an initializer and can call it from anywhere. Prevents unnecessary mouse-usage.
add a comment |
I've tried so many of these answers unsuccessfully in Rails 4 (wow they changed a thing or two for god sakes) I decided to add my own. The ones that called ActiveRecord::Base.connection and pulled the table names worked but didn't get the result I wanted because I've hidden some models (in a folder inside of app/models/) that I didn't want to delete:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
I put that in an initializer and can call it from anywhere. Prevents unnecessary mouse-usage.
add a comment |
I've tried so many of these answers unsuccessfully in Rails 4 (wow they changed a thing or two for god sakes) I decided to add my own. The ones that called ActiveRecord::Base.connection and pulled the table names worked but didn't get the result I wanted because I've hidden some models (in a folder inside of app/models/) that I didn't want to delete:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
I put that in an initializer and can call it from anywhere. Prevents unnecessary mouse-usage.
I've tried so many of these answers unsuccessfully in Rails 4 (wow they changed a thing or two for god sakes) I decided to add my own. The ones that called ActiveRecord::Base.connection and pulled the table names worked but didn't get the result I wanted because I've hidden some models (in a folder inside of app/models/) that I didn't want to delete:
def list_models
Dir.glob("#{Rails.root}/app/models/*.rb").map{|x| x.split("/").last.split(".").first.camelize}
end
I put that in an initializer and can call it from anywhere. Prevents unnecessary mouse-usage.
answered Nov 14 '13 at 22:25
boulder_ruby
26.3k65873
26.3k65873
add a comment |
add a comment |
can check this
@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}
add a comment |
can check this
@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}
add a comment |
can check this
@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}
can check this
@models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize}
edited Jun 28 '14 at 3:25
zishe
7,962104890
7,962104890
answered May 3 '13 at 10:55
Arvind
1,8401226
1,8401226
add a comment |
add a comment |
Assuming all models are in app/models and you have grep & awk on your server (majority of the cases),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("n")
It it faster than Rails.application.eager_load!
or looping through each file with Dir
.
EDIT:
The disadvantage of this method is that it misses models that indirectly inherit from ActiveRecord (e.g. FictionalBook < Book
). The surest way is Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, even though it's kinda slow.
add a comment |
Assuming all models are in app/models and you have grep & awk on your server (majority of the cases),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("n")
It it faster than Rails.application.eager_load!
or looping through each file with Dir
.
EDIT:
The disadvantage of this method is that it misses models that indirectly inherit from ActiveRecord (e.g. FictionalBook < Book
). The surest way is Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, even though it's kinda slow.
add a comment |
Assuming all models are in app/models and you have grep & awk on your server (majority of the cases),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("n")
It it faster than Rails.application.eager_load!
or looping through each file with Dir
.
EDIT:
The disadvantage of this method is that it misses models that indirectly inherit from ActiveRecord (e.g. FictionalBook < Book
). The surest way is Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, even though it's kinda slow.
Assuming all models are in app/models and you have grep & awk on your server (majority of the cases),
# extract lines that match specific string, and print 2nd word of each line
results = `grep -r "< ActiveRecord::Base" app/models/ | awk '{print $2}'`
model_names = results.split("n")
It it faster than Rails.application.eager_load!
or looping through each file with Dir
.
EDIT:
The disadvantage of this method is that it misses models that indirectly inherit from ActiveRecord (e.g. FictionalBook < Book
). The surest way is Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, even though it's kinda slow.
edited Oct 8 '15 at 22:54
answered Oct 8 '15 at 21:15
konyak
5,08923450
5,08923450
add a comment |
add a comment |
I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.
Let say you have a column public_uid
that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)
Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
you can now run rake di:public_uids:generate
add a comment |
I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.
Let say you have a column public_uid
that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)
Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
you can now run rake di:public_uids:generate
add a comment |
I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.
Let say you have a column public_uid
that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)
Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
you can now run rake di:public_uids:generate
I'm just throwing this example here if anyone finds it useful. Solution is based on this answer https://stackoverflow.com/a/10712838/473040.
Let say you have a column public_uid
that is used as a primary ID to outside world (you can findjreasons why you would want to do that here)
Now let say you've introduced this field on bunch of existing Models and now you want to regenerate all the records that are not yet set. You can do that like this
# lib/tasks/data_integirity.rake
namespace :di do
namespace :public_uids do
desc "Data Integrity: genereate public_uid for any model record that doesn't have value of public_uid"
task generate: :environment do
Rails.application.eager_load!
ActiveRecord::Base
.descendants
.select {|f| f.attribute_names.include?("public_uid") }
.each do |m|
m.where(public_uid: nil).each { |mi| puts "Generating public_uid for #{m}#id #{mi.id}"; mi.generate_public_uid; mi.save }
end
end
end
end
you can now run rake di:public_uids:generate
edited May 23 '17 at 12:02
Community♦
11
11
answered Oct 6 '16 at 9:57
equivalent8
9,13434885
9,13434885
add a comment |
add a comment |
Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
next unless model_path.match(/.rb$/)
model_class = model_path.gsub(/.rb$/, '').classify.constantize
puts model_class
end
This will give to you all the model classes you have on your project.
add a comment |
Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
next unless model_path.match(/.rb$/)
model_class = model_path.gsub(/.rb$/, '').classify.constantize
puts model_class
end
This will give to you all the model classes you have on your project.
add a comment |
Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
next unless model_path.match(/.rb$/)
model_class = model_path.gsub(/.rb$/, '').classify.constantize
puts model_class
end
This will give to you all the model classes you have on your project.
Dir.foreach("#{Rails.root.to_s}/app/models") do |model_path|
next unless model_path.match(/.rb$/)
model_class = model_path.gsub(/.rb$/, '').classify.constantize
puts model_class
end
This will give to you all the model classes you have on your project.
edited Nov 22 at 18:44
answered Nov 22 at 18:35
Victor
8615
8615
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f516579%2fis-there-a-way-to-get-a-collection-of-all-the-models-in-your-rails-app%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
If you need to collect all models including models of Rails engines/railties, see the answer by @jaime
– Andrei
Feb 18 '11 at 11:21
Doesn't work on rails 5.1
– aks
Mar 2 at 15:06