Existe uma maneira de obter uma coleção de todos os modelos no seu aplicativo Rails?
Basicamente, posso fazer o seguinte: -
Models.each do |model|
puts model.class.name
end
Existe uma maneira de obter uma coleção de todos os modelos no seu aplicativo Rails?
Basicamente, posso fazer o seguinte: -
Models.each do |model|
puts model.class.name
end
Respostas:
Edição: Veja os comentários e outras respostas. Existem respostas mais inteligentes do que esta! Ou tente melhorar este como wiki da comunidade.
Os modelos não se registram em um objeto mestre; portanto, o Rails não possui a lista de modelos.
Mas você ainda pode procurar no conteúdo do diretório de modelos do seu aplicativo ...
Edição: Outra idéia (selvagem) seria usar a reflexão Ruby para procurar todas as classes que estendem ActiveRecord :: Base. Não sei como é possível listar todas as classes ...
EDIT: Apenas por diversão, encontrei uma maneira de listar todas as aulas
EDIT: finalmente conseguiu listar todos os modelos sem consultar os diretórios
Se você quiser lidar com a classe derivada também, precisará testar toda a cadeia da superclasse. Eu fiz isso adicionando um método à classe Class:
fonte
RAILS_ROOT
não está mais disponível no Rails 3. Em vez disso, useDir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
agora, portanto, se você carregar todos os modelos com entusiasmo, poderá iterá-los facilmente - veja minha resposta abaixo.A resposta completa para o Rails 3, 4 e 5 é:
Se
cache_classes
estiver desativado (por padrão, está desativado no desenvolvimento, mas ativado na produção):Então:
Isso garante que todos os modelos em seu aplicativo, independentemente de onde eles estejam, estejam carregados e quaisquer gemas que você esteja usando que forneçam modelos também sejam carregadas.
Isso também deve funcionar em classes que herdam de
ActiveRecord::Base
, comoApplicationRecord
no Rails 5, e retornam apenas a subárvore de descendentes:Se você quiser saber mais sobre como isso é feito, consulte ActiveSupport :: DescendantsTracker .
fonte
:environment
para que oeager_load!
trabalho funcione.Rails.application.eager_load!
, você pode apenas carregar os modelos:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
diretórios. O carregamento ansioso de todo o aplicativo é uma resposta mais completa e garantirá que não haja absolutamente nenhum lugar para os modelos serem definidos.Rails.application.paths["app/models"].eager_load!
Apenas para o caso de alguém tropeçar nessa, eu tenho outra solução, não confiando na leitura de dir ou estendendo a classe Class ...
Isso retornará uma matriz de classes. Então você pode fazer
fonte
ActiveRecord::Base.subclasses
mas tem que usarsend
? Além disso, parece que você precisa "tocar" o modelo antes que ele apareça, por exemplo,c = Category.new
e ele apareça. Caso contrário, não vai.ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
aparecer , você ainda precisará "tocar" os modelos antes para listá-los.retornará
Informações adicionais Se você desejar chamar um método no nome do objeto sem modelo: método desconhecido da cadeia ou erros de variáveis, use este
fonte
ActiveRecord::Base.send :subclasses
procurar os nomes das tabelas é uma boa idéia. A geração automática dos nomes dos modelos pode ser problemática, como mencionado anteriormente..capitalize.singularize.camelize
pode ser substituído por.classify
.Procurei maneiras de fazer isso e acabei escolhendo desta maneira:
fonte: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
fonte
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Alguns dos modelos podem não estar ativados; portanto, é necessário resgatá-lo.model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
Para os modelos Rails5 , agora são subclasses de
ApplicationRecord
, para obter a lista de todos os modelos em seu aplicativo, você faz:Ou mais curto:
Se você estiver no modo dev, precisará de modelos de carregamento ansiosos antes:
fonte
Acho que a solução da @ hnovick é legal se você não tem modelos sem mesa. Essa solução funcionaria também no modo de desenvolvimento
Minha abordagem é sutilmente diferente -
classify deve fornecer o nome da classe de uma string corretamente . safe_constantize garante que você possa transformá-lo em uma classe com segurança, sem gerar uma exceção. Isso é necessário caso você tenha tabelas de banco de dados que não são modelos. compacto para que quaisquer nulos na enumeração sejam removidos.
fonte
safe_constantize
.Se você deseja apenas os nomes das classes:
Basta executá-lo no console do Rails, nada mais. Boa sorte!
EDIT: @ sj26 está certo, você precisa executá-lo primeiro antes de poder chamar os descendentes:
fonte
map
computs
? Eu não entendo o ponto deve serActiveRecord::Base.descendants.map(&:model_name)
Isso parece funcionar para mim:
O Rails só carrega modelos quando eles são usados, portanto a linha Dir.glob "requer" todos os arquivos no diretório models.
Depois de ter os modelos em uma matriz, você pode fazer o que estava pensando (por exemplo, no código de exibição):
fonte
...'/app/models/**/*.rb'
Em uma linha:
Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
fonte
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
fonte
Em apenas uma linha:
fonte
Rails.application.eager_load!
antes da execução no modo de desenvolvimento.Ainda não posso comentar, mas acho que a resposta sj26 deve ser a resposta principal. Apenas uma dica:
fonte
Com o Rails 6 , o Zetiwerk se tornou o carregador de código padrão.
Para carregamento rápido, tente:
Então
fonte
Sim, existem muitas maneiras de encontrar todos os nomes de modelos, mas o que eu fiz na minha gema model_info é que ele fornecerá todos os modelos incluídos nas gemas.
então simplesmente imprima isso
fonte
Isso funciona para o Rails 3.2.18
fonte
Para evitar pré-carregar todos os Rails, você pode fazer o seguinte:
require_dependency (f) é o mesmo que
Rails.application.eager_load!
usa. Isso deve evitar erros de arquivo já necessários.Em seguida, você pode usar todo tipo de solução para listar modelos de AR, como
ActiveRecord::Base.descendants
fonte
fonte
Aqui está uma solução que foi examinada com um aplicativo Rails complexo (aquele que alimenta o Square)
Ele pega as melhores partes das respostas neste tópico e as combina na solução mais simples e completa. Este identificador de casos em que seus modelos estão em subdiretórios, use set_table_name etc.
fonte
Acabei de encontrar este, pois preciso imprimir todos os modelos com seus atributos (baseados no comentário de @Aditya Sanghi):
fonte
Isso funcionou para mim. Agradecimentos especiais a todas as postagens acima. Isso deve retornar uma coleção de todos os seus modelos.
fonte
Ele
Rails
implementa o métododescendants
, mas os modelos nem sempre herdamActiveRecord::Base
, por exemplo, a classe que inclui o móduloActiveModel::Model
terá o mesmo comportamento que um modelo, apenas não será vinculado a uma tabela.Então, complementando o que dizem os colegas acima, o menor esforço faria o seguinte:
Patch de Macacos da classe
Class
Ruby:e o método
models
, incluindo ancestrais, como este:O método
Module.constants
retorna (superficialmente) uma coleção desymbols
, em vez de constantes, portanto, o métodoArray#select
pode ser substituído como este patch de macaco doModule
:Remendo de macaco
String
.E, finalmente, o método dos modelos
fonte
Isso fornecerá a você todas as classes de modelo que você tem no seu projeto.
fonte
fonte
Eu tentei muitas dessas respostas sem sucesso no Rails 4 (uau, elas mudaram uma coisa ou duas por amor de Deus) e decidi adicionar as minhas. Aqueles que chamaram ActiveRecord :: Base.connection e puxaram os nomes das tabelas funcionaram, mas não obtiveram o resultado desejado, porque eu ocultei alguns modelos (em uma pasta dentro de app / models /) que eu não queria excluir:
Coloquei isso em um inicializador e posso chamá-lo de qualquer lugar. Impede o uso desnecessário do mouse.
fonte
pode verificar isso
fonte
Supondo que todos os modelos estejam em app / models e você tenha grep & awk no seu servidor (na maioria dos casos),
É mais rápido do que
Rails.application.eager_load!
ou repetindo cada arquivo comDir
.EDITAR:
A desvantagem desse método é que ele perde modelos herdados indiretamente do ActiveRecord (por exemplo
FictionalBook < Book
). O caminho mais certo é queRails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, embora seja meio lento.fonte
Estou apenas jogando este exemplo aqui, se alguém achar útil. A solução é baseada nesta resposta https://stackoverflow.com/a/10712838/473040 .
Digamos que você tenha uma coluna
public_uid
que é usada como um ID primário para o mundo exterior (você pode encontrar perguntas sobre por que você faria isso aqui )Agora, digamos que você introduziu esse campo em vários modelos existentes e agora deseja gerar novamente todos os registros que ainda não foram definidos. Você pode fazer isso assim
agora você pode correr
rake di:public_uids:generate
fonte