I have built a ruby on rails app that lets users track their workouts. User has_many workouts. In addition, a User can create a box (gym) if they are a gym owner. The purpose is to filter activity of users such that they can only see information related to their gym. In this case workouts. On a box show page...I would like to show all users who are associated with that box through a Membership and then consequently the associated users workouts. Here is the set up.
User
class User < ActiveRecord::Base
has_many :boxes
has_many :workouts, :dependent => :destroy
end
Workout
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
Membership
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :box
end
In my /views/boxes/show.html.erb view I have the following:
<% @box.workouts.each do |workout| %>
<%= workout.title %><br/>
<%= workout.user.username %><br/><br/>
<% end %>
which produces no error...but no results. Here is the output from the log
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]
Thoughts on why this isn't working?
I think the problem is that the associations for users memberships to a box gets mixed up with something you might have tried earlier. Because if you look at the last time Workout is loaded in the log:
Workout Load (0.2ms)
SELECT "workouts".*
FROM "workouts"
INNER JOIN "users" ON "workouts".user_id = "users".id
WHERE (("users".box_id = 7))
The WHERE condition indicates that a User belongs_to a box which I can't see from you code. And since you don't get any errors from that line, that field has to exist in the database and you should probably remove it.
Further, you have specified that a User has_many boxes, but it seems like you have forgotten to add that it is through :memberships. I guess the correct way would be:
class User < ActiveRecord::Base
has_many :memberships
has_many :boxes, :through => :memberships
has_many :workouts, :dependent => :destroy
end
And finally, combining two through associations will not work afaik, at least not in this setup. If you want to get all workouts for users in a specific box, then you could do something like this:
#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 %>
The call to :include is of course not necessary but it will generate one sql query instead of 1+n
精彩评论