views:

48

answers:

2

I am creating a survey application so I created a surveys controller that behaves very restfully creating, updating, etc a Survey. However now I'm adding other actions to it like 'take', for taking a survey, and 'share', for sharing a survey. There are more actions too. I'm starting to wonder if I should organize my code differently and move those new actions into their own controllers however I'm not so sure take or share or some of my other actions really fit into REST really well. They almost make more sense as actions if I wasn't a little worried about the survey controller size.

Either I could leave it the way it is or I was thinking of creating a survey namespace and creating like Survey::TakeController and the Survey::ShareController. Then I would then I guess use the new action or index?

I'm not exactly sure the proper way to do it. If I do create a survey namespace should I then move the orginal SurveyController in it? That would make some weird looking methods like survey_survey_path.

A: 

If you want to stay with the RESTful approach then you could have a SurveyParticipation resource, with the new/create actions being invoked when somebody takes a survey. And a, ahem, SurveyShare resource for sharing a survey. That name's pretty awkward though!

Personally I don't think it's the end of the world if you have to augment your existing controllers with a small number of additional actions, as long as it doesn't get out of hand. RESTful Rails saved us from the bad old days when controllers had tens of actions.

John Topley
You would do that instead Survey::Participation and Survey::Share?My worry is that it is hard for me to know just how many other actions. There could possibly be 14 or 15 maybe.
hadees
+4  A: 

To think RESTfully, you should probably stop thinking of them as "controllers with actions" and start thinking of them as "objects that can be created/updated etc" - controllers are just proxies for the views that show the results of creating/updating an object.

A lot of the time, I've found that an extra action is really just a variation of "update" - just with its own special requirements (eg only certain people can update it or whatever). That sort of logic can often go inside the model itself (eg "MyModel#can_be_edited_by?(some_user)").

Sometimes you find that actually you have an extra "hidden" model that needs its own RESTful interface.

Eg with your "take" a survey - I'm guessing, but what you have is something like a "SurveyResult" and a person can "create "survey" but when they "take" a survey, they are actually creating a "SurveyResult" (the other commentor called this a "SurveyParticipation" - but it's the same thing).

The thing being that you will probably have multiple SurveyResults that each belong_to :survey and belong_to :some_user_model.

Then you can set up nice restful routes such as: /surveys/123-my_favourite_colour/results

which will return a set of all the results for a single survey

This is actually the RESTful way to view this part of your object-space.

As to sharing a survey - that's a more intersting question. It depends on how you've got your authorisation setup for "sharing". It also depends on what you mean by "share". Are you sharing the results of a survey, or sharing the survey-object itself (so another user can edit the questions) or are you (as a person that has just taken part in a survey) sharing a link to the survey so that your friends can also take the survey?

For the first two above - I'd consider a "SurveyPermission" class that belongs_to :survey and belongs_to :some_user_model. The you can create a SurveyPermission for another user - and Surveys can be edited by the creator- or anybody that has a permission to edit it. Thus the share action is to create a SurveyPermission. Though to be honest - your SurveyPermission is likely only to be used for create and delete, so it may be simpler to stick those two actions in the Survey controller.

For the latter - well, that's just sending a "create_survey_result(@survey)" link to somebody...

Update:

I don't generally bother with namespaces unless there are two resources named the same thing (but in different contexts). You only need namespaces to disambiguate between them and that doesn't seem to be the case here.

In this case - the only namespacing that occurs is in the routing:

map.resources :surveys do |s|
  s.resources :results
  s.resources :shares # ???
end

gives such routes as:

new_survey_path
surveys_path
new_survey_result_path(@survey)
survey_results_path(@survey)
Taryn East
Share is actually creating something to post to facebook, linkedin, and twitter simultaneously. So I a SurveyShare controller makes sense then. But would you create a namespace survey? and would the SurveyController actually go in it. survey_survey_path seems weird.
hadees