Route not generated, what have I missed?

Hey Guys, I'm basing this off of the book Simply Rails 2 by Patrick Lenz. I've got my word model:

# word.rb has_many :votes

my vote mode;

# vote.rb belongs_to :word, :counter_cache => true

my routes # routes.rb map.resources :words, :has_many => :votes

Then my problem. In my view I'm trying to use a generated url for a form button to create a vote # index.html.erb (in the words folder) <% @words.each do |word| %>   <tr>     <td><%=h word.word %></td>     <td><%=h word.user_id %></td>     <td><%=h word.votes_count %></td>     <td><%= link_to 'Show', word %></td>     <td><%= link_to 'Destroy', word, :confirm => 'Are you sure?', :method => :delete %></td>     <div id="vote_form">       <% form_tag :url => word_votes_path do %>         <%= submit_tag 'shove it' %>       <% end %>     </div>   </tr> <% end %>

word_votes_url failed to generate from {:action=>"index", :controller=>"votes"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["words", :word_id, "votes"] - are they all satisfied?

I was under an impression having the has many and belongs to relationships in the model, as well as the defined route would generate the words_votes_path for me. It works in the book example and I can't find any other defining attributes that I'm lacking but i must be missing something.

Thanks, I was so confident after I went through the multiple demos of rails. But seem to be catching snags on much more then expected on my own project.

word_votes_url needs word id to generate the url, therefore {:action=>"index", :controller=>"votes"} alone is not sufficient. You need to pass word id as well.

See rake routes for all the paths/url generated and ids they need.

Thanks, Abhinav

Brilliant! I don't know why but what you said just made it click for me.

I changed my form to:       <% form_tag word_votes_path :word_id => word.id do %>         <%= submit_tag 'shove it' %>       <% end %>

The votes get created and the counter_caches work like expected. The only other thing i notice is the ugly action method it creates: <form action="/word/votes?definition_id=2" method="post">

where as the simply rails demo produced: <form action="/stories/6-a-fancy-new-story/votes" method="post" onsubmit="new Ajax.Request('/stories/6-a-fancy-new-story/votes', {asynchronous:true, evalScripts:true, parameters:Form.serialize (this)}); return false;">

I realize the major difference is the use of form_remote_tag which creates the ajax but thats not really the concern. Just the better looking action url

In theory couldn't I get mine to look something like: /word/2/votes

? Thanks for the info so far.

Hi Brian,

You can modify your code like this as well:             <% form_tag word_votes_path(word) do %> # note word as argument               <%= submit_tag 'shove it' %>             <% end %>

I am not aware of simply rails demo, but in general, word/2/votes corresponds to index (get) or create (post) action, and it's not a good idea to change the behaviour. You can add a new action in your votes resource and call it something like say "count" and then submit your remote form to this new "count" path.

See rails routing guide to understand more about routes, and how to add new actions: Rails Routing from the Outside In — Ruby on Rails Guides

Thanks, Abhinav

Hey, Create is exactly what the form goes to now which is why I don't get why it hasn't created the word/2/votes route as create (post) is the desired behavior. As well I've tried using word_votes_path(word) and I actually receive this generated output: <form action="/word/votes.%23%3Cword:0x2818ed4%3E" method="post">

** Just found my problem, I was using map.resource :word, :has_many => :votes but needed: map.resources :words, :has_many => :votes

it now generates the correct desired url. words/1/votes

Thanks for your help Abhinav !