10
votes

Trouver tous de type polymorphe dans des rails?

Y a-t-il un moyen de trouver tous les modèles polymorphes d'un type polymorphe spécifique dans des rails? Donc, si j'ai le groupe, l'événement et le projet avec une déclaration comme:

has_many: assignations ,: as =>: Assignable

Puis-je faire quelque chose comme:

assignable.all

... ou

intégréRailsPolymorphichelper.all ("assignable")

Ce serait bien.

EDIT:

... tel que assignable.all renvoie [événement, groupe, produit] (tableau de classes)


1 commentaires

J'ai changé ma réponse en fonction des informations supplémentaires que vous avez données. Je pense que cela traitera de votre besoin.


5 Réponses :


-1
votes

Vous devriez pouvoir simplement utiliser la collection associée: xxx


3 commentaires

Cela retournera tous les attributions pour une instance de modèle. Je pense qu'il veut retourner tous les affectations pour un type.


Mais vous ne pouvez pas simplement dire événement.Assiffrents.all?


Rails n'ajoute pas d'assistants de l'association statique. Donc événement.Assignments lancera nométhoderror .



16
votes

Il n'y a pas de méthode directe pour cela. J'ai écrit ce patch de singe pour activerecord :: base code>. Cela fonctionnera pour n'importe quelle classe.

Assignable.all_polymorphic_types(:assignable).map(&:to_s)
# returns ['Project', 'Event', 'Group']


9 commentaires

Comment puis-je implémenter cela? Est-ce que je vais à la classe aciverecord :: base à modifier? Je ne peux pas sembler trouver cette classe dans mon projet ..


@James Reportez-vous à cette réponse: Stackoverflow.com/Questtions/2328984/ ...


C'est beau! N'a-t-il pas un moyen d'éviter d'avoir à ouvrir les fichiers modèle ? Ne les rails ne connaît pas déjà toutes les classes?


@Augustinriedinger dans le mode de produit que vous pouvez utiliser activerecord :: base.subclasses , en mode Dev, les classes sont chargées uniquement après leur référence explicitement. Donc, ce n'est pas trop fiable. Mon approche lit les noms de fichiers (pas le contenu) et il est fait une fois pour la durée de vie du processus. Donc, il est tolérable ..


Ouais je le google aussi. Le fait qu'il soit lu qu'une seule fois le rend acceptable en effet. Mais il serait même plus agréable qu'il charge au démarrage au lieu d'un appel au premier appel parce que le premier est réellement beaucoup plus lent ...


@Augustinriedinger, vous pouvez ajouter un fichier d'initialisateur ( config / initialiseurs / actif_record.rb ) à votre projet et appelez activerecord :: base. all_polymorphic_types ('foo') en elle.


Oui, mais je voulais dire pour toute la Classe. Ce qui signifie que l'ouverture du dossier modèles , sauf si elle est chargée au début.


@Augustinrieinger Calling Activerecord :: base. all_polymorphic_types charge toutes les classes.


Impressionnant. Cela devrait vraiment faire partie de AR lui-même. Énormément utile par exemple pour la construction de formes.



0
votes

J'ai créé une classe de modèle polymorphe avec une méthode 'all' pour tester cela. XXX PRE>

Voici ma configuration de l'application: P>

User < ActiveRecord::Base
  belongs_to :profile, :polymorphic => true
end

Student < ActiveRecord::Base
  has_one :user, :as => :profile
end


2 commentaires

Pour obtenir ce travail dans le développement Enviroment, vous devez exiger les fichiers de modèles.


Ceci est une classe spéciale, ne descend pas d'ActionCord.



1
votes

Vous pouvez également essayer de cette façon. Casser au-dessus de la solution ne fonctionne pas pour moi parce que j'ai eu du modèle de Mongo.

get_has_many_associations_for_model("assignments", "assignable")


0 commentaires

1
votes

La solution HARRISH SHETTY ne fonctionnera pas pour les fichiers de modèlePachets qui ne sont pas stockés directement dans Rails.root / app / modèles mais dans un sous-répertoire. Bien qu'il gobe correctement des fichiers dans les sous-répertoires, il ne parvient pas à inclure le sous-répertoire lors du changement de nom de fichier en une constante. La raison en est que le sous-rédirateur de noms de noms est supprimé par cette ligne:

  def self.all_polymorphic_types(name)
    @poly_hash ||= {}.tap do |hash|
      Dir.glob(File.join(Rails.root, "app", "models", "**", "*.rb")).each do |file|
        file.sub!(File.join(Rails.root, "app", "models"), '')
        file.sub!('.rb', '')
        klass = file.classify.constantize rescue nil
        next unless klass.ancestors.include?(ActiveRecord::Base)

        klass.
          reflect_on_all_associations(:has_many).
          select{ |r| r.options[:as] }.
          each do |reflection|
            (hash[reflection.options[:as]] ||= []) << klass
          end
      end
    end
    @poly_hash[name.to_sym]
  end


0 commentaires