views:

82

answers:

3

Not sure how to frame this question (I'm still wrapping my head around Rails).

Let's try this:

Say I wanted to implement the user side of Ryan Bates' excellent railscast on nested models. (He shows how to implement a survey where you can add and remove questions and answers dynamically). I want the user's side of this: to be able to answer questions and, not in the tutorial, be able to add comments.

It seems to me that you have to implement a view that shows the questions and answers, allow selection of the answers, and the input of comments. So there would need to be a way to show the information, but also update the model on input, right?

I know I'm not explaining this very well. I hope you understand what I'm getting at.

Is it just a question of setting up the right routes? Or is there some controller mojo that needs to happen?

A: 

In ASP.NET MVC there are two controller methods with the same name but different parameter signatures. One method is decorated with an attribute that tells it to service GETs, the other is decorated with an attribute that tells it to service POSTs. The GET method displays the view, the POST method updates the model.

I assume that it works in a similar fashion in Rails.

Robert Harvey
+1  A: 

You need a "question" resource, "answer" resource and "comment" resource. You also need to implement:

  • POST for "answer (which is "create" method in controller) to answer the question
  • POST for "comment" (which is "create" method in controller) to create comments
  • PUT for the "question" (which is "update" in controller) to "pick" answers, which is effectively changing the state of the "question" resource
Zepplock
OK, got that. Thanks. Now how do I access them in the views?
thermans
I'm just curious: is it only possible to get POST/PUT/GET/DELETE routes if you use the built in CRUD methods in the controller?
Robbie
@thermans: the views will have correspondent names: like "create.html.erb". You can find those in "views" folder. I would suggest looking at "scaffold" generation which will generate model/view/controller for you with all CRUD operations (including routes)@Robbie: you can customize a route to enable/disable POST/PUT/GET/DELETE per resource, as well as add new paths (methods) to the existing routes
Zepplock
+1  A: 

The typical way to do this in Rails uses "resourceful" routing, which more or less naturally maps the standard CRUD actions to methods in your controller, using the appropriate HTTP verbs.

In the routes file (config/routes.rb), you set up the desired resources and actions. For example:

map.resources :questions, :has_many => :answers

Would set up a routing scheme for a question with multiple answers, mapping to the actions according to Rails' conventions:

index: GET /questions/1/answers # list of answers for question id=1
show: GET /questions/1/answers/2 # display answer 2
new: GET /questions/1/answers/new # render form for new answer for question id=1
create: POST /questions/1/answers # create a new answer for question id=1
edit: GET /questions/1/answers/2/edit # render form for answer for question id=1
update: PUT /questions/1/answers/2 # update answer 2
destroy: DELETE /questions/1/answers/2 # delete answer 2

In the controller you create methods mapping to these standard actions. You can also create your own methods and actions for things that don't fall into the CRUD paradigm (like a search for an AJAXified autocomplete field, for example)

Hope that answers some of your question.

zetetic
I guess what I'm confused about (and this goes for Zepplock's answer too), is do I set up a parallel series of controllers and views for the user side of Ryan's survey example, and if so, doesn't that defeat the DRY paradigm? I essentially want a read-only version of the app, where I can view and interact with the survey, but only to answer questions and add comments. I can't get my head around this.
thermans
If the views are otherwise the same, and the only difference is to show certain elements depending on the role of the viewer, you're probably best off using a single controller and view, and wrap the "private" sections with an `if` statement.
zetetic