Button invokes "update" instead of "index"

I have nested resources

  resources :dicts do     resources :cards   end

and in my form

  form_for [@dict,@card] do |f|

I have the following button:

  <%= f.submit('LIST ALL', url: dict_cards_path(@dict.id), class:'kanren_button', name:'list_all', method: :get) %>

The generated HTML code is:

   <input class="kanren_button" method="get" name="back_to_list" type="submit" url="/dicts/6/cards" value="BACK TO LIST" />

I would expect that clicking this button would call Card.index, but I get instead the error message

  The action 'update' could not be found for CardsController

It is correct that I don't have a CardsController.update yet, but I don't think I should need one at this point.

The output from 'rake routes|grep card' looks fine for me:

    dict_cards GET /dicts/:dict_id/cards(.:format) cards#index                POST /dicts/:dict_id/cards(.:format) cards#create new_dict_card GET /dicts/:dict_id/cards/new(.:format) cards#new edit_dict_card GET /dicts/:dict_id/cards/:id/edit(.:format) cards#edit      dict_card GET /dicts/:dict_id/cards/:id(.:format) cards#show                PATCH /dicts/:dict_id/cards/:id(.:format) cards#update                PUT /dicts/:dict_id/cards/:id(.:format) cards#update                DELETE /dicts/:dict_id/cards/:id(.:format) cards#destroy

What did I do wrong?

The method and url parameters you have in the submit helper that show up in the output are going to be ignored, they aren’t valid parameters for submit. Those items are actually defined above in the html form tag (which is generated from your form_for statement). My guess is that if you look at the log, this is coming across with an action of PATCH or PUT.

Does this mean that I can't solve this with a *button*, but would have to use a *link* instead?

Does this mean that I can't solve this with a *button*, but would have to use a *link* instead?

It's important to note that you may style a link to look like anything -- even a button. But you cannot remove the button-ness from an actual button and have it do anything besides submit the form containing it.

Walter

Walter Davis wrote in post #1150186:

Does this mean that I can't solve this with a *button*, but would have to use a *link* instead?

It's important to note that you may style a link to look like anything -- even a button. But you cannot remove the button-ness from an actual button and have it do anything besides submit the form containing it.

I see. Maybe I'm using the wrong design here in the first place. Here is what I am going to do:

The user arrives the web page in question, from an overview page. The overview page gives a list of all instances (in this case, of type Card), by listing only the primary key of the instance. When the user clicks on one of those keys, s/he arrives at a page displaying all the data for this Card instance.

At this point, I will give the user three choices:

- delete the Card - edit the Card - show again the "list of all cards"

My (probably stupid) idea was to write a "form" without input fields, showing only the information on the cards, and having 3 buttons for DELETE, EDIT and LIST.

Now I understand that a submit button in a form helper for a form_for, which has as argument an existing object, automatically calls the "update" function. Thinking about it, this makes sense, and I now think that I was misusing the form_for().

Maybe I should just output the data without using a form at all, and use button_to() if I want the clickable part look or behave like buttons, or use links and style them as buttons, as you pointed out. In any case, using a form in my particular case, doesn't make much sense. Would you agree on that?

I have nested resources

resources :dicts do

resources :cards

end

and in my form

form_for [@dict,@card] do |f|

I have the following button:

<%= f.submit(‘LIST ALL’, url: dict_cards_path(@dict.id),

class:‘kanren_button’, name:‘list_all’, method: :get) %>

The generated HTML code is:

<input class=“kanren_button” method=“get” name=“back_to_list”

type=“submit” url=“/dicts/6/cards” value=“BACK TO LIST” />

URL + method are properties of the “form” tag, not of the submit button. This will not work.

A better question: what is this button supposed to do? It appears to be on a form that’s editing a particular card…

–Matt Jones

Walter Davis wrote in post #1150186:

Does this mean that I can't solve this with a *button*, but would have to use a *link* instead?

It's important to note that you may style a link to look like anything -- even a button. But you cannot remove the button-ness from an actual button and have it do anything besides submit the form containing it.

I see. Maybe I'm using the wrong design here in the first place. Here is what I am going to do:

The user arrives the web page in question, from an overview page. The overview page gives a list of all instances (in this case, of type Card), by listing only the primary key of the instance. When the user clicks on one of those keys, s/he arrives at a page displaying all the data for this Card instance.

At this point, I will give the user three choices:

- delete the Card - edit the Card - show again the "list of all cards"

My (probably stupid) idea was to write a "form" without input fields, showing only the information on the cards, and having 3 buttons for DELETE, EDIT and LIST.

Now I understand that a submit button in a form helper for a form_for, which has as argument an existing object, automatically calls the "update" function. Thinking about it, this makes sense, and I now think that I was misusing the form_for().

Maybe I should just output the data without using a form at all, and use button_to() if I want the clickable part look or behave like buttons, or use links and style them as buttons, as you pointed out. In any case, using a form in my particular case, doesn't make much sense. Would you agree on that?

I think you would get a lot of mileage out of reading the REST article in Rails Guides. Particularly try to absorb how Rails does its own flavor of REST routing. To delete an object, you send a DELETE (header) request, which Rails simulates as a POST with a method: '_delete' hidden field, since most browsers don't properly support that request type. If you were to hand-make a form with such a method within it, wrapped around your delete button, then it would just work. But if you put that button inside a regular form_for @your_object, then the form will have either the POST (new object) or PUT/PATCH (existing object being updated) path and header, and the delete will fail.

Walter