2010-12-02 5 views
0

J'ai créé une application ruby ​​on rails qui permet aux utilisateurs de suivre leurs entraînements. L'utilisateur a_many séances d'entraînement. En outre, un utilisateur peut créer une boîte (gymnase) s'il est propriétaire d'une salle de sport. Le but est de filtrer l'activité des utilisateurs de sorte qu'ils ne puissent voir que les informations relatives à leur salle de sport. Dans ce cas, des séances d'entraînement. Sur une page de présentation de boîte ... Je voudrais montrer à tous les utilisateurs qui sont associés à cette boîte à travers une adhésion et ensuite les entraînements des utilisateurs associés. Voici la mise en place.Problème avec les associations

utilisateur

class User < ActiveRecord::Base 
    has_many :boxes 
    has_many :workouts, :dependent => :destroy 
end 

entraînement

class Workout < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :box 
end 

Box

class Box < ActiveRecord::Base 
    belongs_to :user 
    has_many :users, :through => :memberships 
    has_many :workouts, :through => :users 
    has_many :memberships 
end 

membres

class Membership < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :box 
end 

À mon avis de /views/boxes/show.html.erb Je donne les résultats suivants:

<% @box.workouts.each do |workout| %> 
    <%= workout.title %><br/> 
    <%= workout.user.username %><br/><br/> 
<% end %> 

qui ne produit aucune erreur ... mais aucun résultat. Voici la sortie du journal

Processing BoxesController#show (for 127.0.0.1 at 2010-12-01 22:19:59) [GET] 
    Parameters: {"id"=>"7"} 
    User Load (0.4ms) SELECT * FROM "users" WHERE ("users"."id" = '1') LIMIT 1 
    Box Load (0.3ms) SELECT * FROM "boxes" WHERE ("boxes"."id" = 7) 
    CACHE (0.0ms) SELECT * FROM "boxes" WHERE ("boxes"."id" = 7) 
    User Load (0.4ms) SELECT * FROM "users" WHERE ("users"."id" = 1) 
    Workout Load (0.3ms) SELECT "workouts".* FROM "workouts" INNER JOIN "users" ON "users".id = "workouts".user_id INNER JOIN "boxes" ON "boxes".id = "workouts".box_id WHERE ("workouts"."user_id" = 1) AND ((("workouts"."public" = 1) AND (("users".box_id = 7))) AND (("users".box_id = 7))) ORDER BY created_at DESC 
Rendering template within layouts/application 
Rendering boxes/show 
    User Load (0.6ms) SELECT "users".* FROM "users" INNER JOIN "memberships" ON "users".id = "memberships".user_id WHERE (("memberships".box_id = 7)) 
    Workout Load (0.2ms) SELECT "workouts".* FROM "workouts" INNER JOIN "users" ON "workouts".user_id = "users".id WHERE (("users".box_id = 7)) 
Rendered shared/_navigation (0.6ms) 
Completed in 104ms (View: 23, DB: 2) | 200 OK [http://localhost/boxes/7] 

Réflexions sur les raisons pour lesquelles cela ne fonctionne pas?

+0

Question évidente ici, mais avez-vous des données qui répondent à ces requêtes? En outre, quel code manque, pourquoi y a-t-il des "entraînements". "Public" = 1' dans la requête? – Todd

+0

Belle prise J'allais aborder cela dans une deuxième question. J'ai un named_scope dans Workout.rb parce que les entraînements peuvent être publics ou privés basés sur l'élection d'un champ entier workout.public. Je filtre par si workout.public == 1. Je sais que j'aurais dû faire différemment. – bgadoci

Répondre

2

Je pense que le problème est que les associations pour les appartenances d'utilisateurs à une boîte se mélangent avec quelque chose que vous avez peut-être déjà essayé. Parce que si vous regardez la dernière fois la séance d'entraînement est chargé dans le journal:

Workout Load (0.2ms) 
SELECT "workouts".* 
FROM "workouts" 
INNER JOIN "users" ON "workouts".user_id = "users".id 
WHERE (("users".box_id = 7)) 

La condition WHERE indique qu'un utilisateur belongs_to une boîte que je ne vois pas de code. Et puisque vous n'obtenez aucune erreur de cette ligne, ce champ doit exister dans la base de données et vous devriez probablement le supprimer.

En outre, vous avez spécifié qu'un utilisateur possède plusieurs cases, mais il semble que vous ayez oublié d'ajouter qu'il s'agit de: appartenances. Je suppose que la bonne façon serait:

class User < ActiveRecord::Base 
    has_many :memberships 
    has_many :boxes, :through => :memberships 
    has_many :workouts, :dependent => :destroy 
end 

Enfin, en combinant deux à des associations ne fonctionnera pas afaik, du moins pas dans cette configuration. Si vous souhaitez obtenir toutes les séances d'entraînement pour les utilisateurs dans une zone spécifique, alors vous pourriez faire quelque chose comme ceci:

#In Controller 
@box_users = @box.users.all(:include => :workouts) 

#In View 
<% @box_users.each do |user| %> 
    <% user.workouts.each do |workout| %> 
    <%= workout.title %> 
    <%= user.username %> 
    <% end %> 
<% end %> 

L'appel à: include est bien sûr pas nécessaire, mais il va générer une requête SQL au lieu de 1+ n

+0

C'est génial et ça a l'air de marcher. Une question de suivi. J'ai une portée nommée dans Workout.rb: 'named_scope: public_workouts,: conditions => {: public => 1}'. Est-il de toute façon à filtrer les séances d'entraînement par cela. Peut-être modifier le '@box_users = @ box.users.all (: include =>: workouts)' d'une manière ou d'une autre? – bgadoci

+0

Eh bien, vous pourriez faire comme <% user.workouts.public_workouts.chaque faire | entraînement | %> mais je pense que cela annulera le: include car il faudra probablement interroger la base de données pour chaque utilisateur ... – DanneManne

+0

Le seul problème que je vois avec ce qui se passe ici est que les entraînements ne répondent pas correctement à: order = > "created_at DESC" en ce sens qu'il semble les ordonner au sein de chaque utilisateur au lieu de globalement. Cela a-t-il du sens? – bgadoci

Questions connexes