8
votes

Comment rendre tous les enregistrements d'un ensemble imbriqué dans un véritable arbre HTML

J'utilise le awesome_netés_set_set plugin dans mon projet My Rails. J'ai deux modèles qui ressemblent à ceci (simplifié): xxx

L'arborescence de la base de données est construite comme prévu. Toutes les valeurs de parent_id , lft et rgt sont corrects. L'arbre a plusieurs nœuds racines (ce qui est bien sûr autorisé dans awesome_netés_set_set ).

MAINTENANT, je veux rendre toutes les catégories d'un client donné dans un arbre correctement triché de structure: Par exemple, Nettères

    tags. Ce ne serait pas trop difficile, mais j'en ai besoin d'être efficace (moins les requêtes SQL sont mieux meilleures).

    Mise à jour: a compris qu'il est possible de calculer le nombre de Enfants pour tout nœud donné dans l'arborescence sans autre requête SQL: number_of_children = (nœud.rgt - nœud.lft - 1) / 2 . Cela ne résout pas le problème, mais cela peut s'avérer utile.


0 commentaires

7 Réponses :


3
votes

Vous devez faire de manière récursive une partielle qui s'appellera elle-même. Quelque chose comme ceci: xxx

c'est des rails 2.3 Code. Vous devrez appeler les itinéraires et nommer le partiel explicitement avant cela.


1 commentaires

Ouais, j'ai moi-même trouvé la même solution moi-même. Le problème est que chaque appel à enfants exécute une requête SQL supplémentaire (100 sous-arbres = 100 requêtes SQL). Entraîne un problème classique N + 1. C'est exactement ce que j'essaie d'éviter. En outre: le premier appel partiel de rendu devrait être quelque chose comme <% = rendu: partiel => @ Customer.Catégories.roots%>



5
votes

J'ai répondu à un Question similaire Pour PHP récemment (Set imbriqué == Modèle de travers de pré-commande pré-commande modifié).

Le concept de base est d'obtenir les nœuds déjà commandés et avec un indicateur de profondeur au moyen d'une requête une requête SQL . À partir de là, il s'agit simplement d'une question de rendre la sortie via une boucle ou une récursivité, il devrait donc être facile de convertir cela en rubis.

Je ne connais pas le fichier awesome_netés_set_set plug in, mais il peut déjà contenir une option pour obtenir la profondeur annotée, indiquée, car il s'agit d'une jolie opération / besoin standard lorsqu'il s'agit de ensembles.


0 commentaires

7
votes

Ce serait bien si les ensembles imbriqués avaient de meilleures fonctionnalités hors de la boîte ne le feraient pas.

Le truc tel que vous avez découvert consiste à construire l'arbre à partir d'un ensemble plat: p>

  • Commencez par un ensemble de tous les nœuds triés par LFT LI>
  • Le premier nœud est une racine l'ajoutez que la racine de l'arborescence passe au nœud suivant li>
  • S'il s'agit d'un enfant du nœud précédent (LFT entre Prev.LFT et Prev.RHT) ajoutez un enfant à l'arborescence et avancez un nœud Li>
  • Sinon, passez au niveau de l'arbre un niveau et répétez le test li> ul>

    Voir ci-dessous: P>

    def tree_from_set(set) #set must be in order
      buf = START_TAG(set[0])
      stack = []
      stack.push set[0]
      set[1..-1].each do |node|
        if stack.last.lft < node.lft < stack.last.rgt
          if node.leaf? #(node.rgt - node.lft == 1)
            buf << NODE_TAG(node)
          else
            buf << START_TAG(node)
            stack.push(node)
          end
        else#
          buf << END_TAG
          stack.pop
          retry
        end
      end
      buf <<END_TAG
    end
    
    def START_TAG(node) #for example
      "<li><p>#{node.name}</p><ul>"
    end
    
    def NODE_TAG(node)
      "<li><p>#{node.name}</p></li>"
    end
    
    def END_TAG
      "</li></ul>"
    end 
    


2 commentaires

Cela marche. Vous avez raison en ce qui concerne Awesome_neDe_set. Je ne peux pas m'empêcher de me demander pourquoi cela n'est pas intégré au plugin en premier lieu. THX!


J'ai oublié de mentionner: Le point essentiel de votre solution est que cela ne nécessite qu'une seule requête SQL!



3
votes

_tree.html.eb xxx

_item.html.erb xxx

Vous pouvez également trier leur suivant: < Pré> xxx

mais dans ce cas, vous devez supprimer cette ligne: xxx


0 commentaires

5
votes

Depuis septembre 2009, un ensemble imbriqué génial comprend une méthode spéciale pour le faire: https://github.com/collectiveidea/awesome_nested_set/commit/9fcaaff3d6b351b11c4b40dc1f3e37f33d0a8cbe

Cette méthode est beaucoup plus efficace que le niveau d'appel, car il ne nécessite aucune requête de base de données supplémentaire.

Exemple: catégorie.each_with_level (catégorie.root.elf_and_descendants) Do | O, niveau |


0 commentaires

1
votes

Je ne pouvais pas faire travailler la réponse acceptée à cause de la vieille version de Ruby, je suppose. Voici la solution qui fonctionne pour moi: xxx

Il est simplifié en utilisant les informations en option de profondeur. (L'avantage de cette approche est qu'il n'est pas nécessaire que l'entrée définie soit la structure entière sur les feuilles.)

solution plus complexe sans profondeurs ne peut être trouvée sur Github Wiki de la gemme:

https://github.com/collectiveDea/awesome_nedesté_set/wiki/how-to-generate-Nesté-unorded-list-tags-with-one-db-hit


0 commentaires

1
votes

Peut-être un peu de retard mais j'aimerais partager ma solution pour awesome_nemet_set_set basé sur fermeture_tree gem nié hash_tree méthode: xxx

Cela fonctionnera avec n'importe quelle portée commandé par lft

que d'utiliser l'assistant pour le rendre: xxx


0 commentaires