Why do edit links in this Rails view have the same id? - ruby-on-rails

In this model, scheduled games and players are nested resources of franchise, with routing set up as follows:
OTH::Application.routes.draw do
resources :franchises do
resources :scheduled_games
resources :players
end
I can create these model objects correctly. But I must be doing something wrong in the view, which looks like this:
<% #franchise.scheduled_games.each do |game| %>
<p class="games">
<span class="date">
<b>Opponent:</b> <%= game.opponent %>
<b>date:</b> <%= game.date %>
<%= link_to 'Edit',edit_franchise_scheduled_game_path(#franchise) %>
</span> </p>
<% end %>
There are two things that are going wrong when this view is displayed. The worst is that each edit link has the same id for the nested resource (/franchises/1/scheduled_games/1/edit) even though the other information for the item is correct.
Second is that a blank record always displays.
Where have I gone wrong?
Update Here is the output of rake routes:
franchise_scheduled_games
GET /franchises/:franchise_id/scheduled_games(.:format) {:action=>"index", :controller=>"scheduled_games"}
POST /franchises/:franchise_id/scheduled_games(.:format) {:action=>"create", :controller=>"scheduled_games"}
new_franchise_scheduled_game
GET /franchises/:franchise_id/scheduled_games/new(.:format) {:action=>"new", :controller=>"scheduled_games"}
edit_franchise_scheduled_game
GET /franchises/:franchise_id/scheduled_games/:id/edit(.:format) {:action=>"edit", :controller=>"scheduled_games"}
franchise_scheduled_game
GET /franchises/:franchise_id/scheduled_games/:id(.:format) {:action=>"show", :controller=>"scheduled_games"}
PUT /franchises/:franchise_id/scheduled_games/:id(.:format) {:action=>"update", :controller=>"scheduled_games"}
DELETE /franchises/:franchise_id/scheduled_games/:id(.:format) {:action=>"destroy", :controller=>"scheduled_games"}
franchise_players
GET /franchises/:franchise_id/players(.:format) {:action=>"index", :controller=>"players"}
POST /franchises/:franchise_id/players(.:format) {:action=>"create", :controller=>"players"}
new_franchise_player
GET /franchises/:franchise_id/players/new(.:format) {:action=>"new", :controller=>"players"}
edit_franchise_player
GET /franchises/:franchise_id/players/:id/edit(.:format) {:action=>"edit", :controller=>"players"}
franchise_player
GET /franchises/:franchise_id/players/:id(.:format) {:action=>"show", :controller=>"players"}
PUT /franchises/:franchise_id/players/:id(.:format) {:action=>"update", :controller=>"players"}
DELETE /franchises/:franchise_id/players/:id(.:format) {:action=>"destroy", :controller=>"players"}

You need to specify the game as well when using link_to with nested resources:
edit_franchise_scheduled_game_path(#franchise, game)

Because they use the REST pattern, so if you want to delete a resource you use the HTTP/Delete request to the same url as you would for a GET request.

Related

Rails: Routing without plurals gives strange helpers

I am getting a strange named helpers with this setup:
In config/routes.rb I have:
Qtl::Application.routes.draw do
resources :qtl_table do
collection do
get 'search'
end
end
...
end
rake routes outputs this:
search_qtl_table_index GET /qtl_table/search(.:format) {:action=>"search", :controller=>"qtl_table"}
qtl_table_index GET /qtl_table(.:format) {:action=>"index", :controller=>"qtl_table"}
POST /qtl_table(.:format) {:action=>"create", :controller=>"qtl_table"}
new_qtl_table GET /qtl_table/new(.:format) {:action=>"new", :controller=>"qtl_table"}
edit_qtl_table GET /qtl_table/:id/edit(.:format) {:action=>"edit", :controller=>"qtl_table"}
qtl_table GET /qtl_table/:id(.:format) {:action=>"show", :controller=>"qtl_table"}
PUT /qtl_table/:id(.:format) {:action=>"update", :controller=>"qtl_table"}
DELETE /qtl_table/:id(.:format) {:action=>"destroy", :controller=>"qtl_table"}
and I do have plurals turned off:
ActiveRecord::Base.pluralize_table_names = false
but I get this error:
undefined local variable or method `search_qtl_table_index' for #<#<Class:0x8056a3fa8>:0x8056a2338>
This is related to this question which I will delete soon:
Rails: routing and path helpers
This has nothing to do with pluralizing. YOu need to use search_qtl_table_index_path when you reference it rather than just search_qtl_table_index (you need to add the _path to the end).
So, your form_tag statement should be:
<%= form_tag search_qtl_table_index_path, :method => 'get' do %>

Route missing on nested route

Not sure why this isn't working. It was working perfectly and then I restarted the server. I am getting a no route error:
No route matches {:action=>"new", :controller=>"issues"}
Here is the helper i am trying to call:
<%= link_to "Add Issue", new_app_issue_path %>
and my routes file:
resources :apps do
resources :issues
end
Why would it break all of a sudden? And I obviously have the route:
app_issues GET /apps/:app_id/issues(.:format) {:action=>"index", :controller=>"issues"}
POST /apps/:app_id/issues(.:format) {:action=>"create", :controller=>"issues"}
new_app_issue GET /apps/:app_id/issues/new(.:format) {:action=>"new", :controller=>"issues"}
You need to specify what app this is for:
new_app_issue_path(an_app_object_or_an_app_objects_id)
Rails would only "guess" this if params[:app_id] was available, which doesn't appear to be the case here.

Ruby on Rails: link_to action, no route matches

I'm getting into Rails and trying to add a "vote" feature on a blog setup from here: http://guides.rubyonrails.org/getting_started.html
In app/controllers/posts_controller.rb I created this:
def incvotes
#post = Post.find(params[:id])
post.update_attributes(:upvotes => 1 )
format.html { redirect_to(#post, :notice => 'Vote counted.') }
format.xml { head :ok }
end
In app/views/posts/index.html.erb I created this:
<%= link_to 'Vote', :controller => "posts", :action => "incvotes", :id => post.id %>
But the link is giving the error
No route matches {:controller=>"posts", :action=>"incvotes", :id=>1}
I'm missing something here, but not sure what.
rake routes:
incvotes_post POST /posts/:id/incvotes(.:format) {:action=>"incvotes", :controller=>"posts"}
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"}
POST /posts(.:format) {:action=>"create", :controller=>"posts"}
new_post GET /posts/new(.:format) {:action=>"new", :controller=>"posts"}
edit_post GET /posts/:id/edit(.:format) {:action=>"edit", :controller=>"posts"}
post GET /posts/:id(.:format) {:action=>"show", :controller=>"posts"}
PUT /posts/:id(.:format) {:action=>"update", :controller=>"posts"}
DELETE /posts/:id(.:format) {:action=>"destroy", :controller=>"posts"}
home_index GET /home/index(.:format) {:action=>"index", :controller=>"home"}
root /(.:format) {:action=>"index", :controller=>"home"}
try
= link_to "vote", incvotes_post_path(post), :method=>:post
and if that doesn't work, try changing the method to :put
My guess is that you probably do not have a definition in your routes file for the action you just defined in the controller. Both an action in the controller and an action in the routes file must be defined for Rails to generate urls correctly.
Your routes file probably has something like this:
resources :posts
But you want to add more than the standard actions generated by the resources keyword, so try something like this:
resources :posts do
member do
post 'incvotes'
end
end
This tells routes that you have another action in your posts controller called incvotes that accepts HTTP post requests as long as they are pointed at a member route with the correct action (/posts/14 is a member route, while /posts/ is a 'collection' route). So you will have a new route probably like /posts/14/incvotes that you can post a form to and everything should start working properly.
EDIT:
Actually I guess since you are just adding 1 to an attribute on a model, you don't need a POST action (which are normally associated with posting forms as with create and update). To send a post, you might need to change the HTML in the view to include a form and have it post to the correct url. So you can try that, or you can change your routes file to read get 'incvotes' instead of post 'incvotes'. Sorry for the confusion, hope that helps!
The incvotes_post route only accepts a HTTP POST, and a link always produces a HTTP GET.
Use a form with a button instead (or do a POST using AJAX).
Try using button_to instead link_to:
In your view:
<%= button_to 'Vote', incvotes_post_path(post) %>
In your config/routes.rb add the route to incvotes action as post:
resources :posts do
member do
post 'incvotes'
end
end
And in your controller, create the incvotes action:
def incvotes
# Something
redirect_to :posts
end

How to modify a link?

I need to modify this link to go to
channels/params[:channel_id]/messages
here is the current link
<%= link_to pluralize(#channel.messages.size, 'message') %>
result of rake routes
{:action=>"index", :controller=>"messages"} POST /channels/:channel_id/messages(.:format)
{:action=>"create", :controller=>"messages"}new_channel_message GET /channels/:channel_id/messages/new(.:format)
{:action=>"new", :controller=>"messages"} edit_channel_message GET /channels/:channel_id/messages/:id/edit(.:format)
{:action=>"edit", :controller=>"messages"}channel_message GET /channels/:channel_id/messages/:id(.:format)
{:action=>"show", :controller=>"messages"} PUT /channels/:channel_id/messages/:id(.:format)
{:action=>"update", :controller=>"messages"} DELETE /channels/:channel_id/messages/:id(.:format)
{:action=>"destroy", :controller=>"messages"} channels GET /channels(.:format)
{:action=>"index", :controller=>"channels"} POST /channels(.:format)
{:action=>"create", :controller=>"channels"} new_channel GET /channels/new(.:format)
{:action=>"new", :controller=>"channels"} edit_channel GET /channels/:id/edit(.:format)
{:action=>"edit", :controller=>"channels"}channel GET /channels/:id(.:format)
{:action=>"show", :controller=>"channels"}PUT /channels/:id(.:format)
{:action=>"update", :controller=>"channels"} DELETE /channels/:id(.:format)
If you would have used nested routes and if you redirect that link to index action in messages controller, then you can define your link like this:
<%= link_to pluralize(#channel.messages.size, 'message'), channel_messages_path(#channel) %>
You don't really need to "modify" it, since it most likely never worked anyway :)
Search for the path macro for your route, using:
rake routes
Then you can use the correct macro, which most likely is something like channel_message. You'll reach something like this:
<%= link_to pluralize(#channel.messages.size, 'message'), channel_message_path(#channel) %>

POST request in namespaced resource controller going to index action instead of create

I have a namespaced controller for some admin functionality. My create form does not work -- it ends up routing the request to the index action instead of the create action.
Why isn't the POST getting routed to the create action as it should (being RESTful)?
routes.rb:
map.namespace :admin do |admin|
admin.resources :events
end
rake routes:
admin_events GET /admin/events {:action=>"index", :controller=>"admin/events"}
formatted_admin_events GET /admin/events.:format {:action=>"index", :controller=>"admin/events"}
POST /admin/events {:action=>"create", :controller=>"admin/events"}
POST /admin/events.:format {:action=>"create", :controller=>"admin/events"}
new_admin_event GET /admin/events/new {:action=>"new", :controller=>"admin/events"}
formatted_new_admin_event GET /admin/events/new.:format {:action=>"new", :controller=>"admin/events"}
edit_admin_event GET /admin/events/:id/edit {:action=>"edit", :controller=>"admin/events"}
formatted_edit_admin_event GET /admin/events/:id/edit.:format {:action=>"edit", :controller=>"admin/events"}
admin_event GET /admin/events/:id {:action=>"show", :controller=>"admin/events"}
formatted_admin_event GET /admin/events/:id.:format {:action=>"show", :controller=>"admin/events"}
PUT /admin/events/:id {:action=>"update", :controller=>"admin/events"}
PUT /admin/events/:id.:format {:action=>"update", :controller=>"admin/events"}
DELETE /admin/events/:id {:action=>"destroy", :controller=>"admin/events"}
DELETE /admin/events/:id.:format {:action=>"destroy", :controller=>"admin/events"}
app/views/admin/events/new.html.erb:
<h1>New event</h1>
<% form_for([:admin, #event]) do |f| %>
<%= f.error_messages %>
...
app/controllers/admin/event_controller.rb:
class Admin::EventsController < ApplicationController
def index
#events = Event.find(:all)
...
end
def create
#event = Event.new(params[:event])
...
end
...
end
And finally, a bit of a log file where you can see it is indeed POSTing:
Processing Admin::EventsController#index (for 127.0.0.1 at 2008-10-16 18:12:47) [POST]
Session ID: ...
Parameters: {"commit"=>"Create", "authenticity_token"=>"...", "action"=>"index", "controller"=>"admin/events", "event"=>{"location"=>""}}
Event Load (0.000273) SELECT * FROM `events`
Rendering template within layouts/application
Rendering admin/events/index
Completed in 0.00757 (132 reqs/sec) | Rendering: 0.00118 (15%) | DB: 0.00027 (3%) | 200 OK [http://localhost/admin/events]
The order of the routes was the issue. I'm not sure exactly why, but moving it below my root routes (map.connect '') solves the issue, and Rails routes the requests accordingly.

Resources