7
votes

Comment extraire une "table" d'un tableau d'activerecord dans des rails?

J'ai plusieurs modèles similaires (Contactemail, Contactletleter, ContactPostalCard).

Chaque instance (enregistrement) dans, disons, a été envoyée à un modèle de messagerie spécifique à un contact spécifique.

donc , chacun (par exemple, la prise en contact *) appartient à: Contact

donc, dans le modèle ContactMail, il y a un attribut contactemail.contact_id p> Chaque contact a un nom d'attribut virtuel.

Donc, lorsque j'écris ce qui suit, je recevrai tous les courriels envoyés dans un ensemble spécifique de conditions (dans ce cas, heure): < Pré> xxx

donc, @ sent_emails.Size me dirait le total de tous les e-mails envoyés.

Mon défi: Comment extraire-je plus de granularité, par une entreprise unique à travers les différents modèles?

La sortie que je veux ressemblerait aux éléments suivants: xxx

SO COMPRESSION3 a 2 appels, ce qui signifie qu'il y avait deux enregistrements de contacts de contact où le SENT_Date est tombé entre les deux dates et où le contact associé appartient à Société 3.

La société 1-3 n'est pas définie à l'avance. Il doit être extrait de la piscine de ContactCalls, des contactsetters et des contacts de contacts .....

Le défi est que je ne sais pas ce que sont les entreprises. Ce sont des attributs de la partie des contacts de chaque enregistrement distinct. Donc, dans certains cas, je peux avoir la société2 a 0 lettres.

Merci pour toute guidage! :)

Comment puis-je trouver une entreprise sur un enregistrement donné pour le modèle ContactMail: xxx

Ceci retournera le Société pour un Conservateur spécifique


0 commentaires

4 Réponses :


0
votes

À mon avis, essayez d'extraire ces données dans une requête (que je suppose que vous voulez faire) est un peu trop excédentaire. Je voudrais émettre une requête pour chaque type avec : groupe => Nom_pompanier option. Ensuite, je fusionnerais les résultats en utilisant le code Ruby, donc j'ai une structure de données permettant une affichage facile (probablement un hachage de hachage, par exemple {'société 1' => {'appels' => 5, 'lettre' => 0, 'Postalcards' => 3 '} ...} .


5 commentaires

Que fait l'option: groupe =>? Est-ce que cela me donnera le total dans un groupe (je suppose que le groupe SQL, non?)


Comment rechercher par Company_Name lorsque Company_Name est un attribut de contact, que chaque contactage 'appartiendrons_to »? Puis-je créer un attribut virtuel pour chaque ContactTerrage de contacts, Contactletter qui est également Nom? Nom?


Comment puis-je interroger sur tous les modèles (Contactemail, Contactletleter, etc.)


: Groupe => Nom de la société est identique à celui de SQL, mais à partir d'autres réponses, je vois que vous devez plutôt utiliser : groupe => 'société_id' . Et comme je l'ai dit, le faire dans une requête est surkill IMHO, mais vous pouvez voir le code pour cela dans la réponse du complétatif.


Je veux juste que le moyen le plus simple soit le plus simple de le faire .... la société BTW est un attribut virtuel en contact, il a une relation appartiens_to ....



0
votes

Si vous voulez vraiment avoir tous les contacts avec le nombre de toutes ces relations, il pourrait être une bonne idée d'utiliser un compteur_cache.

http://api.rubyonrails.org/classes/actieCord/associations/classmethods.html - Trouvez le cache de la page sur cette page

Ce qu'elle fait est automatiquement de garder un suivi dénormalisé du nombre de relations avec chacune des relations de contact, vous n'avez donc pas à interroger des informations à partir de toutes les tables regroupant par le contact, ce qui pourrait entraîner des problèmes de performance.

Ce que vous devez faire est d'ajouter des colonnes 'emails_count', "lettres_count" et "postcards_count" à votre table "Contacts", mettez-le à la mettre à jour au début, et déclarez vos relations HAS_MANY comme telles: < Pré> xxx

Avec ces configurations, tout ce que vous avez à faire est de faire appel à vos contacts et de vérifier leur cache de compteur pour rendre votre table. Son numéro sera automatiquement mis à jour par rails à chaque fois qu'un élément est créé ou détruit pour ce contact.


4 commentaires

Si je voulais faire référence, par exemple, des informations supplémentaires trouvées dans le modèle ContactInail, je ne le ferais pas, non? Le contre-cache est juste un numéro d'agrégat?


Oui c'est vrai. Vous pouvez toujours, à chaque contact, accéder à leurs contacts_Meimils, mais pas sans faire une requête supplémentaire pour chacune interne. Si vous avez des détails sur quel type d'informations vous souhaitez afficher sur les colonnes agrégées, nous pourrions peut-être vous aider à vous aider. Ps. Peut-être la peine d'être donnée à cette idée, sauf si vous souhaitez charger tout le contenu des 4 tables simultanément dans la mémoire. Pour les tables qui poussent de manière dynamique, c'est généralement une idée à éviter.


D'accord. Alors, permettez-moi de penser que ma question affiche ce que je veux montrer pour l'instant, alors je devrais faire de la contre-cache pourrait travailler ... Sauf que je dois être capable de filtrer par date. Ce nombre, alors, par définition changerait de manière dynamique. à droite?


La même sortie a été remplie de données d'échantillon ... mais la structure globale reste identique (le nombre total d'enregistrements de contacts de contacts (celles-ci pourrait être pour le même contact, BTW) groupé par la société ... merci! Merci!



0
votes

Oh, alors j'avais mal compris votre question au début. Je pense que j'obtiens enfin ce que tu veux dire.

Donc, le seul bon moyen de faire ce que vous voulez (qui tire toutes les données de toutes ces tables) consiste à émettre un indice lors de la requête pour les contacts: P>

<% @companies.each do |company_name, contacts| %>
    Company: <%= company_name %>
    <% contacts.each do |contact| %>
       Contact: <%= contact.name %>
          Emails : <%= contact.contact_emails.map(&:email).split(',') %>
          etc..
    <% end %>
<% end %>


8 commentaires

Salut, merci - désolé j'ai un peu perdu ... Comment puis-je faire la méthode .Count? Je joue également avec les statistiques Gem, qui peut également me donner le nombre de contacts, disons des contacts dans une période donnée. Une idée cool sur la compagnie avec le hachage ... Contactez-vous à un contact. Le contact est-il ci-dessus en référence au modèle spécifique?


Oh je vois ... alors je pouvais faire contact.Contact_emails.count?


"Est-ce que le contact ci-dessus faisant référence au modèle spécifique?" - Oui, comme vous le faites 'Contactemail.All: Conditions => {: Contact_id => 1}' Pour obtenir tous les courriels du premier contact, 'Contact.Tall' retournera tous les contacts dans un tableau. Ensuite, vous pourriez obtenir tous les courriels avec 'contact.first.contact_emails'.


"Oh je vois ... alors je pouvais faire contact.Contact_emails.count?" - En fait, vous voudriez utiliser "contact.contact_emails.size", puisque vous avez déjà chargé toutes les données lorsque vous avez appelé "contact.Tous: include =>: contact_emails". C'était moi en supposant que vous avez besoin de plus que le compte (par vos réponses à mon autre réponse). Si vous voulez vraiment seulement le comte, mon autre réponse est ce que vous voulez (le cache du compteur)


Je vois ... Le défi est de pouvoir les regrouper par la société et non par un contact spécifique. Je peux faire Contactemail.Contact.company.nom Pour générer le nom de la société associée à n'importe quel contact de Conservateur spécifique .... Est-ce que cela aide?


Je pensais que lorsque vous avez dit "chaque contact a un attribut virtuel société_name", cela signifiait que vous obtiendrez le nom de la société via "contact.company_name" et non "contact.company.name" comme vous le mentionnez. Dans les deux sens, la façon de les regrouper par la société est de faire ce que j'ai mentionné ci-dessus: @Companies = @ Contact.Group_By (&: Société_Name). Ce ne devrait pas être un défi du tout, il vous suffit de les regrouper à travers des «contacts» au lieu de «contacts». Qu'est-ce que vous n'avez pas compris ou pourquoi ne pas travailler pour vous?


Dites-vous quoi, je pense que vous pourriez simplement nous montrer de vraies données de chacun des modèles, et exactement quelles informations que vous souhaitez afficher sur la table, sinon cela continuera à aller d'avant en arrière.


Je suppose que je suis confondu par le fait que votre exemple a un "contact:" de sortie comme s'il souhaite produire des contacts spécifiques. Découvrez ma matrice - J'ai juste besoin du nombre de contacts envoyés dans le délai spécifique de la société spécifique (mais les sociétés ne sont pas connues à l'avance ... elles sont extraites de l'information Conservateur, par exemple, sur la base du Contact.



2
votes

Cela devrait le faire bien: xxx


29 commentaires

BTW, Nom d'entreprise Comme indiqué ci-dessus est un attribut virtuel ... Donc, je ne pense pas que cela fonctionne sur SELECTS?


Ouais ne peut pas trouver le nom de l'entreprise car pas une colonne - voir la note que j'avais ... elle doit être accessible via Contact.company.name


Pour que cette solution fonctionne, il faut utiliser jointure externe , i.e. rejoindre extérieur gauche au lieu de rejoindre gauche .


La jointure gauche est la même que la jointure extérieure gauche.


Sur la base de la nature de la question, je pense que le schéma DB a peut-être été conçu sans avoir examiné les fonctions qu'il aurait besoin de soutenir. Je ne suis pas sûr de comprendre pourquoi vous voudriez un attribut virtuel tel que le nom de la société et ne pas avoir de cartographie dans la DB.


hmm ... Comment dois-je le changer? La raison en est qu'un contact appartient à une entreprise, mais une entreprise a_many contacts. C'est comme ça que c'est configuré .... que suggéreriez-vous?


Calling Company_name Un attribut virtuel était trompeur. Il serait préférable de dire que la société est une association de contact, comme votre dernier commentaire. Puisqu'il s'agit d'une association, elle peut être jointe à celle des autres tables. Voir le code mis à jour ci-dessus. Je pense que c'est un bon exemple pour comprendre soigneusement. Notez que la jointure gauche signifie que tout contact sans entreprise sera regroupé dans la même rangée. Assurez-vous de comprendre pourquoi les jointures de gauche sont utilisées ici au lieu de la jointure par défaut (intérieure).


En fait, la société est un attribut virtuel. Il y a un moyen d'obtenir l'association via contact.company.name, que nous pouvons faire, mais j'ai créé l'attribut virtuel de simplicité. Je devrai examiner pourquoi la gauche rejoignée ... Je pense Je l'obtiens ... mais laissez-moi lui donner un aller, thakns!


Je reçois une erreur: Sqlite3 :: sqlexception: non de cette colonne: Société.Id: Sélectionner des sociétés.name Company_Name, Compter (Contact_Mails.Id) Email_count, comptage (Contact_letters.id) Letter_Count, Compte (Contact_Postalcards.Id) Postalcard_Count de "Contacts "Sociétés de jointures de gauche Sociétés de société.Id = Contact.company_id a laissé rejoindre contact_emails sur contact_emails.Contact_id = contacts.Id rejoindre contact_letters sur contact_letters sur contact_letters.contact_id = contacts.Id rejoindre contact_postalcards.Contact_id = Contacts.Id Groupe par société.Id


J'ai fait des ajustements et obtenez maintenant une erreur lorsqu'il arrivera à P: P itemP.comPany_Name, item.email_count, item.letter_count, élément.postalcard_count


Bonjour, je reçois 'nil' - ne jointe-t-il pas à un "nil" s'il y a un résultat nul pour l'une des sélectionnées? Donc, s'il n'y a pas de contact_letters du tout, tout zéros dehors?


Pas sûr de l'erreur avec l'appel "P". C'est juste pour le débogage vraiment, afin que vous puissiez voir ce qu'il va produire. Quelle est l'erreur?


Je reçois un érort alors changé contact.company_id sur contacts.company_id et société.Id aux entreprises.ID


Une jointure intérieure ne chargera pas de lignes à moins d'une ligne correspondante de chaque côté de la jointure. C'est pourquoi j'ai mis à gauche rejoindre à la place. Cela signifie que la table à gauche, c'est-à-dire des sociétés, sera toujours chargée, qu'il y ait ou non des correspondances dans les autres tables.


hmm ... bien le p dites trop d'arguments, donc je réduit l'argument à seulement 1 item.company_name, mais je reçois un nil


Eh bien, ce n'est que du code de débogage de toute façon afin que vous puissiez voir les résultats, chaque élément de la matrice sera un objet de type société et ces appels de méthode sont générés dynamiquement à partir des termes définis dans la sélection. Tout se ressemble bien à moi. Essayez de faire chacun à la fois.


Voyons ... Je suis allé et je l'ai fait it Item.Inspect et il génère #


J'ai donc apporté des changements partout dans la déclaration de jointure, il était singulier et pluralisé depuis que je suppose qu'il doit faire référence à un nom de table ... je veux juste m'assurer ... Mais je reçois un nil, ce qui ne devait pas arriver parce que Il y a des enregistrements de contact_imails


hmm ... Le comte a l'air correct ... il ne semble pas que le nom de la société soit à droite ... il sort comme "# "


Droite, chaque élément de tableau sera une instance de contact (j'ai précisément ladite entreprise avant). Chaque élément de la: Sélectionner la clause sera ajouté sous forme d'attributs virtuels à chaque instance renvoyée par la requête. Donnez ceci un essai: liste [0] .attributes.Inspect , etc.


Intéressant, répertoriez les attributs fonctionne plutôt bien: {"postalcard_count" => 3, "email_count" => 3, "lettre_count" => 0, "Société_name" => "typhon corporation"} Mais je reçois une sortie bizarre quand Accéder à l'élément.company_name?


Oh, vous avez un conflit entre votre méthode d'attribut virtuel probablement. Modifiez le: sélectionnez-vous à autre chose et utilisez-le à la place.


Je vois .... Dois-je supprimer l'attribut virtuel, j'essayais d'être légèrement plus simpliste que toujours appeler contact.company.nom, mais je ne sais pas si le Select le reconnaîtra. Company_Name est-il juste la valeur qui détient le résultat de cette colonne à partir de l'instruction SELECT?


ok, cool, je pense que c'était un conflit avec contact.company_name car l'élément est un objet de contact, donc j'ai changé le nom de la sélection de CO_NAME et il semble qu'il fonctionne! J'ai juste besoin de valider les mathématiques, mais il semble juste ... merci! Espérons-le, pas de problèmes, mais la dirigeant par des données de production pour le voir, merci :)


Comportement impair - Lorsque j'essaie d'afficher tous les contacts, je vois 2. Mais cela montre un comté_email à 3, le même numéro que Count_PostalCard. Les pensées?


ah, quelque chose est étrange - je viens d'envoyer un autre email pour voir ce qui se passerait ... * Les deux * postalcards et e-mails sont allés à 5 au lieu de 4 pour Just Count_email ... sonne comme quelque chose est d'être quelque chose est d'être Double-compté ...?


Je pense que la façon dont il fait le comte ou le regroupement fait quelque chose de funky ... Je ne sais pas comment il appartient à 5, lorsque le nombre réel est 3 total, 2 pour un contact, et 1 pour un autre ... Donc, un contact est à double compter ....


Salut, est-ce une façon de comprendre pourquoi il compte les choses funky?


Désolé, je ne me suis pas averti quand il y a un nouveau commentaire à moins que je me connecte (allez sur Stackoverflow !!). La meilleure façon de déboguer quelque chose comme ceci est de trouver l'instruction SQL dans le fichier journal et de l'exécuter manuellement dans le client DB. Ensuite, vous pourriez enlever le groupe par entièrement, et cela vous montrerait chaque ligne de sélection. Vous pouvez modifier les colonnes dans la sélection afin que vous puissiez découvrir ce qui se passe. Il sera utile que vous fassiez cet exercice, ce sera un outil d'apprentissage très utile et quelque chose que vous utiliserez beaucoup dans le futur.