web-dev-qa-db-fra.com

Rails: obtenir des données d'une table pour chaque itération d'une boucle

J'ai une boucle (pour l'élément dans @dataset) et je veux, à chaque itération, obtenir des données différentes d'une autre table et effectuer certaines opérations qui seront imprimées dans la vue. Je ne peux pas obtenir ces données de l'ensemble de données utilisé dans la boucle.

Comment puis-je faire cela selon MVC? Je peux mettre le code dans la boucle, dans la vue, mais je pense que c'est horrible.

Dois-je utiliser un assistant pour cela et appeler la fonction depuis la vue?

Merci d'avance,

- ARemesal

28
ARemesal

Si vous avez une table et que vous souhaitez obtenir des données d'une autre table, c'est généralement le cas d'un has_many relation. Par exemple, nous avons @people (Person modèle), et chaque personne has_many adresses (modèle Address). Dans ces cas, la meilleure chose à faire est la suivante:

# Controller
@people = Person.find(:all, :include => :addresses)
...

# View
@people.each do |p|
  p.addresses.each do |address|
    ...

Si vos données ne sont pas uniquement des tables de base de données normales (peut-être que vous les obtenez à partir d'un service Web, etc.), alors une bonne chose à faire est de créer toutes les données dans le contrôleur à l'avance, puis de les transmettre à la vue . Quelque chose comme ça

# Controller
@people = Person.find(:all)
@people.each do |p|
  # attach loaded data to the person object in controller
  p.addresses = Address.load_from_somewhere_by_name(p.name)
...

De cette façon, le code d'affichage reste propre, comme ceci:

# View
@people.each do |p|
  p.addresses.each do |address|
    ...
46
Orion Edwards

Si j'étais vous, je créerais une classe distincte qui encapsule l'ensemble de données et contient toute la logique impliquée dans le traitement des entrées de l'ensemble de données. Cette classe pourrait être itérable (répondez à chacun). Ensuite, je passais une instance de cette classe à la vue et n'utilisais que ses méthodes.

1
Adam Byrtek
Person(id, name, other fields...)
Event(id, title, ...)
Date(id, date, time, event_id, ...)
Disponibility(id, percent, date_id, person_id, ...)

Bien sûr, toutes les relations sont définies dans le modèle.

J'ai une vue qui montre toutes les dates d'un événement, c'est facile. Mais je veux, pour chaque date, imprimer les données de toutes les personnes qui sont disponibles pour cette date. À mon avis, en oubliant le modèle de conception MVC, je pourrais coder quelque chose comme ceci:

<% for date in @Dates 
  available = Disponibility.find_by_date_id(date.id)
  for item in available
    guy = Person.find_by_id(item.person_id)
%>

Date de rendu et personnes disponibles ...

Je veux éviter cela dans la vue. Je pense que la réponse d'Orion Edwards est la plus proche de ce dont j'ai besoin, mais, dans cet exemple, l'adresse est un champ vide pour la table Personne? Ou comment puis-je ajouter un nouvel attribut à la classe Person?

Bien que je manque une astuce SQL pour ce faire?

1
Nadeem Yasin

Il est assez difficile de déterminer la meilleure solution à votre problème sans détails sur les données et les relations entre vos modèles (tableaux). L'idée commune est la suivante: gardez vos opinions stupides. Obtenez toutes les données nécessaires pour rendre la vue à l'intérieur de l'action de vos contrôleurs. Effectuez toutes les modifications et tous les calculs dans la même action. Ensuite, utilisez ces données en vue.

btw, si vous parlez d'un problème N + 1, lisez plus sur les paramètres ActiveRecord "include" et "join".

1
IDBD
  • Conservez toute la logique de votre élément @dataset dans l'action du contrôleur
  • Utilisez des méthodes dans vos modèles pour l'interaction avec d'autres objets de modèle dont vous avez besoin
  • Vous devez vous retrouver avec seulement @dataset pour votre vue que vous pouvez rendre dans un partiel.

Vous auriez besoin d'expliquer davantage votre situation pour plus de réponse à ce sujet. Avec quel type d'opérations et d'autres modèles avez-vous besoin d'interagir? Si vous postez vos associations de modèles, je suis sûr que nous pourrions vraiment vous éloigner.

Bonne chance!

0
mwilliams