views:

91

answers:

3

I have a form for a nested resource (Client :has_many Workouts) that I want to pre-populate based on some user input (I use this input to set up some other default parameters for the new action).

<%  form_tag new_client_workout_path(@workout_user) do%>
    <%= date_select nil, :date %>
    <%= submit_tag 'Enter New Workout' %><br/>
<% end %>

If I submit this form I get the following error.

ActionController::MethodNotAllowed Only get, put, and delete requests are allowed.

I can update the form's method to get, which works, but then I have all of my form paramters on the query string which I don't want.

Is there some way to accomplish this using a post?

I've done something similar when the resource wasn't nested and it worked fine.

A: 

I'm not sure if this is directly related to your issue, but when using nested resources, you need to pass both resources to your form tag for it generate the proper routes. Meaning:

<%  form_tag new_client_workout_path(@client, @workout) do %>

I don't know enough about the specifics of what you are doing, so it's a little tough to get you to the answer directly. What is @workout_user? What do your routes look like?

Edit:

After seeing your reply below, the "cleaner way" to do this would be to do:

<%  form_tag(new_client_workout_path(@workout_user), :method => :get) do %>

Note: the guides seem to use a quoted "get", but I think a symbol works as well.

theIV
Are you sure that's right? With a new_ path I'm pretty sure you only need the @client resource (note that I'm trying to go to the NEW action, not the CREATE action). Also, @workout_user is @client in this instance, just used an unconventional variable name.Routes for this are map.resources :clients, :has_many => 'workouts'
John
Good point on new vs. create, I hadn't caught that. You're right in that for the new path, you would only need to be supplying the client, but why is your form pointing at the new path? It sounds to me like you need to add `:method => :get` to your form tag.
theIV
A: 

I was able to get it to work by adding a hidden form field

<%= hidden_field_tag '_method', 'get' %>

so that the form method is post, but the rest method is get

Not sure if I'm doing all this the right way or if there is a more accepted way of getting user input to the new action. Normally, you would get all your user input from the new action, but in this case I'm building the form differently depending on what date the user selects.

John
Based on this answer, I've updated my answer. Cheers.
theIV
+1  A: 

So, as I understand it, you want a form (as shown) to be sent as a POST to a controller which causes another form to be rendered which is pre-populated with date-directed parameters (from the first form), right?

It's unconventional but you could just change the new action of your WorkoutsController so accept a POST instead of the conventional GET. In routes.rb

map.resources :clients do |clients|
  clients.resources :workouts, :new => { :new => :post }
end

UPDATE

The clean RESTful way to do something like this is to have a separate controller (working title - ConfigWorkoutsContoller) and actions (new and create) for the first form as follows;

  • ConfigWorkoutsContoller#new renders the form (as shown) which is a GET
  • Its submit action is a POST to the create action with the date
  • ConfigWorkoutsContoller#create pre-populates a @workout instance and renders WorkoutsController#new
bjg
Yes that's exactly what I want to do. In this case, the user is following a workout plan, so based on the date it will pre-fill in the exercises he/she was supposed to do that day. For that reason, I need to know the date ahead of time vs just having a datepicker on the new workout for. Is there a better pattern for handling a situation like this?
John
@John See my update with a suggested cleaner, RESTful approach
bjg