2010-05-14 2 views
2

J'ai essayé de résoudre ce problème pendant quelques heures maintenant et je n'ai pas réussi à trouver une solution propre. Il semble que je ne suis pas trop bon avec les rails ...Comment trier des objets dans une relation many-to-many en ruby ​​on rails?

Quoi qu'il en soit, je donne les résultats suivants:

Diagram

Dans le code:

class Article < ActiveRecord::Base 
    has_many :line_aspects 
    has_many :aspects, :through => :line_aspects 
    #plus a 'name' field 
end 

class LineAspect < ActiveRecord::Base 
    belongs_to :article 
    belongs_to :aspect 
    #plus a 'value' field 
end 

class Aspect < ActiveRecord::Base 
    has_many :line_aspects 
    has_many :articles, :through => :line_aspects 
    #plus a 'name' field 
end 

Maintenant, ce que je voudrais faire, est de les trier en deux étapes. Première sorte d'articles par leur Articles.name, puis à l'intérieur de les trier par Aspect.name (note, pas l'intermédiaire).

Par exemple, par ordre alphabétique (désolé si la notation est incorrect):

[{ 
    article => 'Apple', 
    line_aspects => [ 
     {:value => 'red'}, #corresponding to the Attribute with :name => 'color' 
     {:value => 'small'} #corresponding to the Attribute with :name => 'shape' 
    ] 
},{ 
    article => 'Watermelon', 
    line_aspects => [ 
     {:value => 'green'}, #corresponding to the Attribute with :name => 'color' 
     {:value => 'big'} #corresponding to the Attribute with :name => 'shape' 
    ] 
}] 

Encore une fois, notez que ceux-ci sont commandés par le nom d'aspect (couleur avant la forme) au lieu des valeurs spécifiques de chaque ligne (rouge avant vert). Mon intention est de les afficher dans une table dans la vue.

Avec ce résultat:

Table

Ce code J'utilise:

<table> 
    <tr> 
    <th>Category</th> 
    <% @articles.each do |article| -%> 
     <th><%= link_to article.name, article -%></th> 
    <% end -%> 
    </tr> 

    <% @aspects.each do |aspect| -%> 
    <tr> 
     <td><%= aspect.name -%></td> 

     <% aspect.line_aspects.each do |line_aspect| -%> 
     <td><%= line_aspect.value %></td> 
     <% end -%> 
    </tr> 
    <% end -%> 
</table> 

Je n'ai pas trouvé une bonne façon de le faire dans des rails encore (sans avoir recours à N requêtes). Quelqu'un peut-il me dire un bon moyen de le faire (même en changeant la vue, si mon approche est fausse)?

(j'ai trouvé un similar question in hyphen)

MISE À JOUR: Voici comment je le ferais dans SQL:

SELECT line_aspects.value FROM line_aspects, aspects, articles 
WHERE articles.id = line_aspects.article_id 
    AND aspects.id = line_aspects.aspect_id 
ORDER BY aspects.name, articles.name 

Mais je voudrais faire le chemin des rails.

MISE À JOUR: Ajout du code de vue. Ce qui pourrait exposer ma situation un peu mieux.

+0

J'ai deux solutions pour trier plusieurs à-plusieurs. voir [la question similaire] (http://stackoverflow.com/questions/10417901/rails-how-to-sort-many-to-many-relation/43781591#43781591) –

Répondre

3

Après avoir essayé l'autre réponse, j'ai trouvé un moyen de le faire à partir du modèle. Je ne suis pas sûr que ce soit le bon moyen, mais il semble être une solution viable (pour laisser le moteur de base de données le trier).

Dans le modèle d'aspect j'ai changé cette ligne:

has_many :line_aspects 

Dans ceci:

has_many :line_aspects, :include => :article, :order => 'articles.name' 

Je voudrais encore entendre plus de gens si possible, cependant.

1

Ceci n'est qu'une solution partielle, car elle ne résout pas entièrement votre problème.

Vous pouvez utiliser named_scope pour commander le modèle par le domaine respectif. Quelque chose du genre: named_scope :ordered, :order => "name ASC"

C'est une solution simple (au moins pour la syntaxe, pas sûre de la complexité). Le seul problème que je peux prévoir est que vous ne pouvez pas composer plusieurs named_scopes pour le tri dans une seule requête.

Pour le deuxième tri, vous pouvez utiliser Enumerable#sort_by ou array.sort sur la collection que vous avez obtenue.

Hope this helps un peu :)

+0

Merci pour l'aide. –

0

Cette requête va chercher tous les articles et les charges avides de ses aspects et les trie par nom de l'article et le nom ascpect:

@articles = Article.all(:include => [ :aspects ], :order => "articles.name asc, aspects.name asc") 
Questions connexes