开发者

Problem with associations

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜