Hi,
After having been given som references concerining this hip new REST
thing (thanks Mathieu) it seems that REST, especially the nested
resources bit, is for me. I am trying to develop a membership
administration application specifi for my sport, so I really like the
idea of being able to “enter” a club and doing everything in the
context of that club in an explicit way (i.e. not setting a session
variable and all that).
This means, of course, that a member is a member of a club. This is
all very good for most situations, however, I would like to develop a
statistics module for the entire organization (i.e. all clubs). Now,
since members is only used within a club, it seems that this would
mean iterating through al clubs, joining the membership lists,
resorting them and THEN begin to dispay statistics. Seems very
un-rails-like.
The suggested solution I can come up with is to have a new model
organisation to which all clubs belong and has a has_many -
relationship with members, through clubs. Then, have a nested resource
where members is in organisation (whith an id which is always 1).
Would this work? Are there potential conflicts involved in having
multiple nested routes with the same resource?
I’m not really a strong enough Rails developer for this so I
appreciate all the help I can get !
/Fredrik
–
“Give up learning, and put an end to your troubles.”
what kind of statistics do you want to provide? Will something like
the following not work?
map.resources :clubs, :collection => { :statistics => :any }
class Club < AR::Base
has_many :members
end
class Member < AR::Base
belongs_to :club
end
class ClubsController < ApplicationController
GET /clubs/statistics
def statistics
@clubs = Club.find(:all, :include => :members, :order => ‘name’)
end
end
clubs/statistics.rhtml
<% for club in @clubs -%>
Name: <%= club.name %>
Number of members: <%= club.members.length %>
… etc
<% end -%>
The simplest approach may be a named route. In your routes.rb you
would add:
map.statistics ‘/
statistics’, :controller=>‘members’, :action=>‘statistics’
That named route would allow you to put something like this in a view:
<%= link_to ‘statistics’, :url=>statistics_url, … %>
Then your controller would:
class MembersController < ApplicationController
def statistics
@members = Member.find(:all, – your statistics criteria here --)
… your additional manipulation here …
respond_to ...
end
end
end
Note that the method in question knows that it deals with all members
generally, not that subset of members belonging to a particular club.
There are a few other options available as well. One would be to have
both a nested and non-nested map.resources statement in your routes.rb
for the members. I’d shy away from this as it could get messy and the
url would not be ‘pretty’ (IMO).
Another would be to create a new controller. A point that many
people miss is that a resource need not have a 1-for-1 correlation to
a model. It could be a subset of the model attributes or a
combination of two or more resources. What’s important is that a
resource be addressable and respond to a certain set of requests.
With that in mind you could consider a ‘statistic’ resource to be the
cumulative totals for a member, the name of the member that compiled
them, and the club for which that member plays. Your
StatisticsController#index would retrieve those in whatever way made
the most sense (probably Member.find(:all, :include=>:club, …)).
Taking that approach you get a pretty url and a view/controller
dedicated to statistics rendering (very clear separation of concerns).
HTH,
AndyV