This is my first rails project and I'm a complete newbie to all code, not just Ruby, so please forgive me if I don't explain my issue concisely.
I have a model, Car, which belongs to another model, User. I want my Cars index page to show all cars in the database, so I made a custom route of '/cars/', rather than the :user_id/cars/:id route generated by Rails.
The Car info is getting output onto my index page, but I can't work out how to generate links back to the Car show page.
I'm sure it's something simple, but I've been reading the Rails Guide and other questions on here all day and haven't fixed it yet.
Here's the block:
<% #cars.each do |car| %>
<li>
<div class="well row <%= cycle('', 'white-bg') %>">
<div class="col-sm-4 text-center">
<!-- thumbnail for car here -->
</div>
<div class="pull-left">
<%= link_to car.id, user_car_path(#user, car) do %>
<h3><%= car.year %> <%=car.make %> <%= car.model %></h3>
<% end %>
</div>
<div>
<h3 class="pull-right"><%= car.price %></h3>
</div>
</div>
</li>
<% end %>
Routes:
get 'cars' => 'cars#index', as: :cars
resources :users do
resource :profile
resources :cars, except: :index
end
end
Controller:
def new
#user = User.find( params[:user_id] )
#car = #user.cars.build
end
# POST request to /users/:user_id/cars
def create
#user = User.find( params[:user_id] )
#car = #user.cars.build( car_params )
if #car.save
redirect_to user_path( params[:user_id] )
end
end
# GET request to /users/:user_id/cars/:id
def show
#user = User.find( params[:user_id] )
#car = #user.cars.find( params[:id] )
end
# GET request to /cars/
def index
#cars = Car.all
end
The error is:
No route matches {:action=>"show", :controller=>"cars", :id=>"1", :user_id=>nil} missing required keys: [:user_id]
I'm guessing I'm missing something in the controller, but everything I've tried in there just generates other errors.
Thanks!
cars_path GET /cars(.:format) cars#index
POST /cars(.:format) cars#create
new_car_path GET /cars/new(.:format) cars#new
edit_car_path GET /cars/:id/edit(.:format) cars#edit
car_path GET /cars/:id(.:format) cars#show
PATCH /cars/:id(.:format) cars#update
PUT /cars/:id(.:format) cars#update
DELETE /cars/:id(.:format) cars#destroy
new_user_profile_path GET /users/:user_id/profile/new(.:format)
profiles#new
edit_user_profile_path GET /users/:user_id/profile/edit(.:format)
profiles#edit
user_profile_path GET /users/:user_id/profile(.:format)
profiles#show
PATCH /users/:user_id/profile(.:format) profiles#update
PUT /users/:user_id/profile(.:format) profiles#update
DELETE /users/:user_id/profile(.:format) profiles#destroy
POST /users/:user_id/profile(.:format) profiles#create
user_cars_path GET /users/:user_id/cars(.:format) cars#index
POST /users/:user_id/cars(.:format) cars#create
new_user_car_path GET /users/:user_id/cars/new(.:format) cars#new
GET /cars/:id/edit(.:format) cars#edit
GET /cars/:id(.:format) cars#show
PATCH /cars/:id(.:format) cars#update
PUT /cars/:id(.:format) cars#update
DELETE /cars/:id(.:format) cars#destroy
I would suggest an alternative solution where you "unnest" the cars resource - and just provide a index route for the cars belonging to a certain user:
# routes.rb
resources :cars
resources :users do
resources :cars, module: 'users', only: [:index]
end
# app/controller/cars_controller.rb
class CarsController < ApplicationController
# GET /cars
def index
#cars = Car.all
end
# show, create, delete, new...
end
# app/controller/users/cars_controller.rb
class Users::CarsController < ApplicationController
# GET /users/:user_id/cars
def index
#user = User.includes(:cars).find(params[:user_id])
#cars = #user.cars
end
end
Depending on the context you can move more of the collection routes (new, create) to Users::CarsController if you for example are able to create cars for other users. Nesting member routes (that act on a single record)
is seldom necessary. You can avoid it by using the shallow: true option:
resources :users do
resources :cars, shallow: true
end
This lets you route to a car by simply doing:
link_to(#car.name, car_path(#car))
# or
link_to(#car.name, #car)
If you decide to keep your current setup you route to nested resource by using an array or keywords:
link_to(#car.name, user_car_path(user: #user, id: #car))
# or
link_to(#car.name, [#user, #car])
Related
I submitted this question yesterday and was mostly able to get the issue solved from the answers I got there, however I'm now having a different but related problem.
I have this code in my show view for my object, Car:
<%= link_to #user do %>
<%= image_tag #user.profile.avatar.url, class: 'user-index-avatar' %>
<h3><%= #user.profile.company %></h3>
<% end %>
<h4><%= #user.profile.location %></h4>
<h4><%= #user.profile.phone_number %></h4>
<h4><%= #user.profile.email %></h4>
<% if user_signed_in? && #user.id == current_user.id %>
<%= link_to "Edit Listing", edit_car_path(id: #car.id ), class: 'btn btn-lg btn-warning btn-block' %>
<% end %>
When I go to this page, I get the error message "ActiveRecord::RecordNotFound in CarsController#show" and "Couldn't find User with 'id'="
Rake routes:
cars GET /cars(.:format) cars#index
GET /cars(.:format) cars#index
POST /cars(.:format) cars#create
new_car GET /cars/new(.:format) cars#new
edit_car GET /cars/:id/edit(.:format) cars#edit
car GET /cars/:id(.:format) cars#show
PATCH /cars/:id(.:format) cars#update
PUT /cars/:id(.:format) cars#update
DELETE /cars/:id(.:format) cars#destroy
new_user_profile GET /users/:user_id/profile/new(.:format) profiles#new
edit_user_profile GET /users/:user_id/profile/edit(.:format) profiles#edit
user_profile GET /users/:user_id/profile(.:format) profiles#show
PATCH /users/:user_id/profile(.:format) profiles#update
PUT /users/:user_id/profile(.:format) profiles#update
DELETE /users/:user_id/profile(.:format) profiles#destroy
POST /users/:user_id/profile(.:format) profiles#create
user_cars GET /users/:user_id/cars(.:format) cars#index
POST /users/:user_id/cars(.:format) cars#create
new_user_car GET /users/:user_id/cars/new(.:format) cars#new
GET /cars/:id/edit(.:format) cars#edit
GET /cars/:id(.:format) cars#show
PATCH /cars/:id(.:format) cars#update
PUT /cars/:id(.:format) cars#update
DELETE /cars/:id(.:format) cars#destroy
Models:
class Car < ActiveRecord::Base
belongs_to :user
end
class User < ApplicationRecord
belongs_to :plan
has_one :profile
has_many :cars
Routes.rb
get 'cars' => 'cars#index', as: :cars
resources :cars
resources :users do
resource :profile
resources :cars, shallow: true
end
CarsController:
def show
#car = Car.find( params[:id] )
#user = User.find( params[:user_id] )
#profile = #user.profile
end
The error specifies the issue is with "#user = User.find( params[:user_id] )", but I'm not sure how else to define #user. As mentioned in the linked problem above, I'm a complete newbie, so please forgive me if this is an obvious fix.
Rails find method raises this exception when it is unable to find a record by a specified id. You can double check your user_id in params and see if that id's record actually exists in database.
And by the error you have pasted, it seems user_id is null in your params.
You can always do some thing like
puts "Look for me in console\n"*10
puts params.inspect
And than see in the log window what params you are actually receiving.
I see your problem is solved in comments by accessing user association in car model, but this answer is intended to point to the root of problem and decrease number of unanswered question in SO :)
The application has: Clients, which has and belongs to many ActionItems, which has and belongs to many Clients. A user, chooses a client (a client they have as a customer), and adds action items (to do's) to that client. -- Like: User creates => "Email client about X topic," for client: Crayola LLC.
I've been instructed to nest resources like so, in routes:
resources :clients do
resources :action_items
end
So that I can get a URL like:
-http://localhost:3000/clients/42/action_items/11
To display the action items for a specific client.
However - deleting action items for that client, doesn't work. It's been trying to redirect me to the destroy action, on which I get:
undefined local variable or method `clients_action_items' for # <ActionItemsController:0x007febd0edf800>
Prior to this, the delete link, which uses the destroy action, was attempting to redirect me to the show page, on which I was getting:
No route matches [POST] "/clients/42/action_items/1"
Then I added: post '/clients/:client_id/action_items/:id' => 'action_items#destroy' to the routes file. (and now I get the undefined local variable or method clients_action_items' error.
Routes:
Rails.application.routes.draw do
get 'users/index'
get 'users/new'
get 'users/edit'
get 'users/delete'
get 'users/create'
patch 'users/create'
patch 'users/update'
get 'clients/index'
get 'clients/new'
get 'clients/edit'
get 'clients/delete' => 'clients#delete'
get 'clients/create'
patch 'clients/create'
patch 'clients/update'
post '/clients/:client_id/action_items/:id' => 'action_items#destroy'
get 'login', :to => "access#index"
resources :action_items
#/clients/13/action_items
resources :clients do
resources :action_items
end
#get 'home/index'
#get 'home/edit'
#
#get 'home/delete'
#get 'home/show'
root 'home#index'
#define, below **, is the URL we named categories/index. It is now localhost:3000/define
#get 'index' => 'questions#index'
#get 'questions/edit'
#get 'new' => 'questions#new'
#get 'questions/delete'
#post 'questions/destroy'
#get 'questions/show'
#post 'create' => 'questions#create'
match ':controller(/:action(/:id))', :via => [:get, :post]
# end
end
Action Items Controller:
class ActionItemsController < ApplicationController
# before_action :get_owner
def index
#action_items = ActionItem.all
#client = Client.find(params[:client_id])
end
def new
#action_items = ActionItem.new
# #action_items_client = #client.action_items.new
#client = Client.find(params[:client_id])
end
def create
# #action_item = ActionItem.new(action_items_params)
# if #action_item.save
# redirect_to(:action => 'show', :id => #action_item.id)
# #renders client individual page
# else
# redirect_to(:action => 'new')
# end
#client = Client.find(params[:client_id])
#action_item_client = #client.action_items.new(action_items_params)
if #action_item_client.save
redirect_to(:action => 'show', :id => #action_item_client.id, :client_id => #client.id)
else
redirect_to(:action => 'new')
end
end
def edit
#action_item = ActionItem.find(params[:id])
end
def update
#action_item = ActionItem.find(params[:id])
if #action_item.update_attributes(action_items_params)
redirect_to(:controller => 'action_items', :action => 'show', :id => #action_item.id)
flash[:notice] = "Updated"
else
render 'new'
end
end
def show
#client = Client.find(params[:id])
#action_item = ActionItem.find(params[:action_item_id])
end
def action_clients
#action_clients = ActionItem.Client.new
end
def delete
#action_item = #client.action_items.find(params[:client_id])
end
def destroy
# #action_items = #client.action_items.find(params[:id]).destroy
# redirect_to(:controller => 'action_items', :action => 'index')
item = clients_action_items.find(params[:client_id])
item.destroy
if params[:client_id]
redirect_to clients_action_items_path(params[:client_id])
else
redirect_to clients_action_items_path
end
end
private
def action_items_params
params.require(:action_item).permit(:purpose, :correspondence_method, :know_person, :contact_name_answer, :additional_notes)
end
# private
# def get_owner
# if params[:client_id].present?
# #owner = user.clients.find(params[:client_id])
# else
# #owner = user
# end
# end
end
Index view from which I am deleting an action item:
<%= link_to('New Action Item', :controller => 'action_items', :action => 'new') %></br>
<ol><% #action_items.each do |list| %>
<li>
Action Item for <%= #client.name %> is: <strong><%= list.correspondence_method %></strong> Client, about:
<strong><%= list.purpose %> </strong></li>
And you created some additional notes: <strong><%= list.additional_notes %></strong></br></br>
-- Crud Actions -- </br>
<%= link_to('New Action Item', :controller => 'action_items', :action => 'new') %></br>
<%= link_to('Edit Action Item', :controller => 'action_items', :action => 'edit', :id => list.id) %></br>
<%= link_to('Show Individual', :controller => 'action_items', :action => 'show', :id => list.id) %></br>
<%= button_to('Delete Action Item', :controller => 'action_items', :action => 'destroy', :id => list.id) %></br>
<h2> new delete </h2>
</br></br>
<% end %></ol>
I have created the foreign key columns in a migration file with a join table called: action_items_clients:
class CreateActionItemsClients < ActiveRecord::Migration
def change
create_table :action_items_clients, :id => false do |t|
t.integer :action_item_id
t.integer :client_id
end
end
end
-New to rails. Please excuse dirty code. What is wrong here? Why the destroy link issues? Why was the destroy link redirecting to show before, and giving me both routing and ID errors?
Thanks for your time.
*** EDIT ****
Rake routes output:
Prefix Verb URI Pattern Controller#Action
users_index GET /users/index(.:format) users#index
users_new GET /users/new(.:format) users#new
users_edit GET /users/edit(.:format) users#edit
users_delete GET /users/delete(.:format) users#delete
users_create GET /users/create(.:format) users#create
PATCH /users/create(.:format) users#create
users_update PATCH /users/update(.:format) users#update
clients_index GET /clients/index(.:format) clients#index
clients_new GET /clients/new(.:format) clients#new
clients_edit GET /clients/edit(.:format) clients#edit
clients_delete GET /clients/delete(.:format) clients#delete
clients_create GET /clients/create(.:format) clients#create
PATCH /clients/create(.:format) clients#create
clients_update PATCH /clients/update(.:format) clients#update
DELETE /clients/:client_id/action_items/:id(.:format) action_items#destroy
login GET /login(.:format) access#index
action_items GET /action_items(.:format) action_items#index
POST /action_items(.:format) action_items#create
new_action_item GET /action_items/new(.:format) action_items#new
edit_action_item GET /action_items/:id/edit(.:format) action_items#edit
action_item GET /action_items/:id(.:format) action_items#show
PATCH /action_items/:id(.:format) action_items#update
PUT /action_items/:id(.:format) action_items#update
DELETE /action_items/:id(.:format) action_items#destroy
client_action_items GET /clients/:client_id/action_items(.:format) action_items#index
POST /clients/:client_id/action_items(.:format) action_items#create
new_client_action_item GET /clients/:client_id/action_items/new(.:format) action_items#new
edit_client_action_item GET /clients/:client_id/action_items/:id/edit(.:format) action_items#edit
client_action_item GET /clients/:client_id/action_items/:id(.:format) action_items#show
PATCH /clients/:client_id/action_items/:id(.:format) action_items#update
PUT /clients/:client_id/action_items/:id(.:format) action_items#update
DELETE /clients/:client_id/action_items/:id(.:format) action_items#destroy
clients GET /clients(.:format) clients#index
POST /clients(.:format) clients#create
new_client GET /clients/new(.:format) clients#new
edit_client GET /clients/:id/edit(.:format) clients#edit
client GET /clients/:id(.:format) clients#show
PATCH /clients/:id(.:format) clients#update
PUT /clients/:id(.:format) clients#update
DELETE /clients/:id(.:format) clients#destroy
root GET / home#index
GET|POST /:controller(/:action(/:id))(.:format) :controller#:action
It seems you are trying to destroy an object using a POST request.
No route matches [POST] "/clients/42/action_items/1"
Did you try a DELETE request?
delete '/clients/:client_id/action_items/:id' => 'action_items#destroy'
You can read further about CRUD (Create, Read, Update, Delete) operations here
Also, can you run rake:routes and post the output here? That will help figure out what routes are actually being generated.
EDIT
So, as you can see from the output of rake:routes there is a LOT of duplication. You basically have three models, User, Client and ActionItems with basic CRUD and one login.
Rake file:
Rails.application.routes.draw do
get 'login', :to => "access#index"
resources :users
resources :action_items
resources :clients do
member do
get :action_items
end
end
root 'home#index'
end
Client and ActionItems have a many-to-many relation. If it was a one-to-many ie many ActionItems belong to only one Client then it would have been better to nest the resources.
To show all action items of a client you only need one extra method in client controller.
Clients Controller:
def show
#client = Client.find(params[:id])
end
def action_items
#list_action_items = #client.action_items
end
Action Items Controller:
#Will list all action_items irrespective of which clients they belong to
def index
#action_items = ActionItem.all
end
#For creating a new action item,
def new
#action_item = ActionItem.new
#You can render a form with dropdown here with Client.all to assign the new action_item to a client
end
def create
#action_item = ActionItem.new(action_items_params)
if #action_item.save
redirect_to(:action => 'show', :id => #action_item.id)
#renders client individual page
else
redirect_to(:action => 'new')
end
end
def edit
#action_item = ActionItem.find(params[:id])
end
def update
if #action_item.update_attributes(action_items_params)
flash[:notice] = "Updated"
redirect_to(:controller => 'action_items', :action => 'show', :id => #action_item.id)
else
render 'new'
end
end
def show
#action_item = ActionItem.find(params[:id])
end
def destroy
#action_item.destroy
flash[:notice] = "Action Item has been deleted."
redirect_to action_items_path
end
I have tried to simplify the structure here. If you want to perform tasks like deleting all action items of a client from the index/list page of all clients, you can define a method destroy_many in the ActionItems controller which takes client_id as argument, queries all action items and deletes them.
You don't need separate ClientActionItem controller/routes.
Also, if you want to continue with nested routes,
try
<%= button_to('Delete Action Item', client_action_item_path(#client.id, list.id), method: :delete) %></br>
The nested route requires two arguments. The first is client.id and second the action_item id.
This should work, but un-tested. I am not sure of your intentions, but I would use a link_to with a class of button personally.
<%= button_to('Delete Action Item', client_action_item_path(#client, list), method: :delete) %></br>
I have a has_many :through association between model Thing and Category, so each one has_many of the other. It works when I create a new Thing and associate it with a Category, and then put Category.name in the Thing view, but then I try to put it as a link, it returns the error "ActionController::UrlGenerationError in Things#show". What am I doing wrong?
Thing Controller
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#category_things = CategoryThing.all
#thing.categories.build
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :image_path, :avatar)
end
def results
end
end
Category Controller
class CategoriesController < ApplicationController
def show
#category = Category.find(params[:id])
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
if #category.save
redirect_to #category
else
render 'new'
end
end
private
def category_params
params.require(:category).permit(:name)
end
def results
end
end
Thing Model
class Thing < ActiveRecord::Base
has_many :category_things
has_many :categories, :through => :category_things
end
Category Model
class Category < ActiveRecord::Base
has_many :category_things
has_many :things, :through => :category_things
end
CategoryThing Model
class CategoryThing < ActiveRecord::Base
belongs_to :category
belongs_to :thing
end
Thing.show View
<div id= "thing">
<p>
<% #thing.categories.each do |category| %>
<%= link_to category.name, category_path(category) %>
*****[THE ABOVE WORKS WHEN I JUST PUT "category.name"]*****
<% end %>
</p>
</div>
Thing.new View
<h1>Add Something!</h1>
<p>
<%= form_for #thing, :url => things_path do |f| %>
<%= f.text_field :name, :placeholder => "Name of the thing" %>
<br>
<%= f.label :categories_the_thing_belongs_to %>
<%= f.collection_select :categories, Category.all, :id, :name %>
<br>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</p>
Output of rake routes
Prefix Verb URI Pattern Controller#Action
ratings_new GET /ratings/new(.:format) ratings#new
down_votes_new GET /down_votes/new(.:format) down_votes#new
thing_new GET /thing/new(.:format) thing#new
good_comments_new GET /good_comments/new(.:format) good_comments#new
good_comments_show GET /good_comments/show(.:format) good_comments#show
bad_comments_new GET /bad_comments/new(.:format) bad_comments#new
related_things_new GET /related_things/new(.:format) related_things#new
things_new GET /things/new(.:format) things#new
category_things_new GET /category_things/new(.:format) category_things#new
thing_ratings_new GET /thing_ratings/new(.:format) thing_ratings#new
category_ratings_new GET /category_ratings/new(.:format) category_ratings#new
subjects GET /subjects(.:format) subjects#index
POST /subjects(.:format) subjects#create
new_subject GET /subjects/new(.:format) subjects#new
edit_subject GET /subjects/:id/edit(.:format) subjects#edit
subject GET /subjects/:id(.:format) subjects#show
PATCH /subjects/:id(.:format) subjects#update
PUT /subjects/:id(.:format) subjects#update
DELETE /subjects/:id(.:format) subjects#destroy
subjects_show GET /subjects/show(.:format) subjects#show
subject_things_new GET /subject_things/new(.:format) subject_things#new
categories GET /categories(.:format) categories#index
POST /categories(.:format) categories#create
new_category GET /categories/new(.:format) categories#new
edit_category GET /categories/:id/edit(.:format) categories#edit
category GET /categories/:id(.:format) categories#show
PATCH /categories/:id(.:format) categories#update
PUT /categories/:id(.:format) categories#update
DELETE /categories/:id(.:format) categories#destroy
categories_results GET /categories/results(.:format) categories#results
subjects_new GET /subjects/new(.:format) subjects#new
root GET / home_page#home
all_things_new GET /all/things/new(.:format) things#new
all_allthings GET /all/allthings(.:format) all#allthings
thing_good_comments GET /things/:thing_id/good_comments(.:format) good_comments#index
POST /things/:thing_id/good_comments(.:format) good_comments#create
new_thing_good_comment GET /things/:thing_id/good_comments/new(.:format) good_comments#new
edit_thing_good_comment GET /things/:thing_id/good_comments/:id/edit(.:format) good_comments#edit
thing_good_comment GET /things/:thing_id/good_comments/:id(.:format) good_comments#show
PATCH /things/:thing_id/good_comments/:id(.:format) good_comments#update
PUT /things/:thing_id/good_comments/:id(.:format) good_comments#update
DELETE /things/:thing_id/good_comments/:id(.:format) good_comments#destroy
thing_bad_comments GET /things/:thing_id/bad_comments(.:format) bad_comments#index
POST /things/:thing_id/bad_comments(.:format) bad_comments#create
new_thing_bad_comment GET /things/:thing_id/bad_comments/new(.:format) bad_comments#new
edit_thing_bad_comment GET /things/:thing_id/bad_comments/:id/edit(.:format) bad_comments#edit
thing_bad_comment GET /things/:thing_id/bad_comments/:id(.:format) bad_comments#show
PATCH /things/:thing_id/bad_comments/:id(.:format) bad_comments#update
PUT /things/:thing_id/bad_comments/:id(.:format) bad_comments#update
DELETE /things/:thing_id/bad_comments/:id(.:format) bad_comments#destroy
thing_ratings GET /things/:thing_id/ratings(.:format) ratings#index
POST /things/:thing_id/ratings(.:format) ratings#create
new_thing_rating GET /things/:thing_id/ratings/new(.:format) ratings#new
edit_thing_rating GET /things/:thing_id/ratings/:id/edit(.:format) ratings#edit
thing_rating GET /things/:thing_id/ratings/:id(.:format) ratings#show
PATCH /things/:thing_id/ratings/:id(.:format) ratings#update
PUT /things/:thing_id/ratings/:id(.:format) ratings#update
DELETE /things/:thing_id/ratings/:id(.:format) ratings#destroy
thing_up_votes GET /things/:thing_id/up_votes(.:format) up_votes#index
POST /things/:thing_id/up_votes(.:format) up_votes#create
new_thing_up_vote GET /things/:thing_id/up_votes/new(.:format) up_votes#new
edit_thing_up_vote GET /things/:thing_id/up_votes/:id/edit(.:format) up_votes#edit
thing_up_vote GET /things/:thing_id/up_votes/:id(.:format) up_votes#show
PATCH /things/:thing_id/up_votes/:id(.:format) up_votes#update
PUT /things/:thing_id/up_votes/:id(.:format) up_votes#update
DELETE /things/:thing_id/up_votes/:id(.:format) up_votes#destroy
things GET /things(.:format) things#index
POST /things(.:format) things#create
new_thing GET /things/new(.:format) things#new
edit_thing GET /things/:id/edit(.:format) things#edit
thing GET /things/:id(.:format) things#show
PATCH /things/:id(.:format) things#update
PUT /things/:id(.:format) things#update
DELETE /things/:id(.:format) things#destroy
things_show GET /things/show(.:format) things#show
things_results GET /things/results(.:format) things#results
things_random GET /things/random(.:format) things#random
web_console /console WebConsole::Engine
Routes for WebConsole::Engine:
root GET / web_console/console_sessions#index
input_console_session PUT /console_sessions/:id/input(.:format) web_console/console_sessions#input
pending_output_console_session GET /console_sessions/:id/pending_output(.:format) web_console/console_sessions#pending_output
configuration_console_session PUT /console_sessions/:id/configuration(.:format) web_console/console_sessions#configuration
console_sessions GET /console_sessions(.:format) web_console/console_sessions#index
POST /console_sessions(.:format) web_console/console_sessions#create
new_console_session GET /console_sessions/new(.:format) web_console/console_sessions#new
edit_console_session GET /console_sessions/:id/edit(.:format) web_console/console_sessions#edit
console_session GET /console_sessions/:id(.:format) web_console/console_sessions#show
PATCH /console_sessions/:id(.:format) web_console/console_sessions#update
PUT /console_sessions/:id(.:format) web_console/console_sessions#update
DELETE /console_sessions/:id(.:format) web_console/console_sessions#destroy
Routes.rb
Website::Application.routes.draw do
get "ratings/new"
get "down_votes/new"
get "thing/new"
get "good_comments/new"
get "good_comments/show"
get "bad_comments/new"
get "related_things/new"
get "things/new"
get "category_things/new"
get "thing_ratings/new"
get "category_ratings/new"
resources :subjects
get "subjects/show"
get "subject_things/new"
resources :categories
get "categories/results"
get "subjects/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things do
resources :good_comments
resources :bad_comments
resources :ratings
resources :up_votes
end
get "things/show"
get "things/results"
get 'things/random' => 'things#random'
end
When submitting my form (_reply_form.html.erb) I get this error:
Routing Error
No route matches [POST] "/responses/replies/4"
Try running rake routes for more information on available routes.
This is how my architecture is set up: Offering has many Responses. Response has many Replies.
I know I need the form to submit to this route, but I can't get it to do that:
response_replies POST /responses/:response_id/replies(.:format) replies#create
_reply_form.html.erb:
<%= form_for(#reply, :url => response_reply_path([#response, #reply])) do |f| %>
<%= render 'common/form_errors', object: #reply %>
<%= f.label :body, "Your Reply" %>
<%= f.text_area(:body, :rows => 10, :class => "field span6") %>
<%= f.submit "Post Reply", :class => "block" %>
<% end %>
_response.html.erb:
<%= render 'replies/reply_form', {:response => #response, :reply => #reply} %>
offerings/show.html.erb:
<% if #offering.responses.any? %>
<%= render #offering.responses %>
<% else %>
<p>This offering has no responses yet.</p>
<% end %>
responses_controller.rb:
class ResponsesController < ApplicationController
before_filter :auth, only: [:create]
def show
#offering = Offering.new
#response = Response.new
#reply = Reply.new
end
def create
#offering = Offering.find(params[:offering_id])
# now that we have our offering we use it to
# build a response with it
#response = #offering.responses.build(params[:response])
# now we get the user who posted the response
#response.user = current_user
if #response.save
flash[:success] = 'your response has been posted!'
redirect_to #offering
else
#offering = Offering.find(params[:offering_id])
render 'offerings/show'
end
end
end
routes.rb:
resources :offerings, except: [:new] do
# makes it easier for us to display
# forms for responses on the offering show page
# allows us to have access to the
# offering that the response is associated to
resources :responses, only: [:create]
end
resources :responses, except: [:new] do
resources :replies, only: [:create]
end
rake routes produces this:
root / dashboard#index
users POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
need_applicants GET /needs/:need_id/applicants(.:format) applicants#index
POST /needs/:need_id/applicants(.:format) applicants#create
new_need_applicant GET /needs/:need_id/applicants/new(.:format) applicants#new
edit_need_applicant GET /needs/:need_id/applicants/:id/edit(.:format) applicants#edit
need_applicant GET /needs/:need_id/applicants/:id(.:format) applicants#show
PUT /needs/:need_id/applicants/:id(.:format) applicants#update
DELETE /needs/:need_id/applicants/:id(.:format) applicants#destroy
needs GET /needs(.:format) needs#index
POST /needs(.:format) needs#create
edit_need GET /needs/:id/edit(.:format) needs#edit
need GET /needs/:id(.:format) needs#show
PUT /needs/:id(.:format) needs#update
DELETE /needs/:id(.:format) needs#destroy
offering_responses POST /offerings/:offering_id/responses(.:format) responses#create
offerings GET /offerings(.:format) offerings#index
POST /offerings(.:format) offerings#create
edit_offering GET /offerings/:id/edit(.:format) offerings#edit
offering GET /offerings/:id(.:format) offerings#show
PUT /offerings/:id(.:format) offerings#update
DELETE /offerings/:id(.:format) offerings#destroy
response_replies POST /responses/:response_id/replies(.:format) replies#create
responses GET /responses(.:format) responses#index
POST /responses(.:format) responses#create
edit_response GET /responses/:id/edit(.:format) responses#edit
response GET /responses/:id(.:format) responses#show
PUT /responses/:id(.:format) responses#update
DELETE /responses/:id(.:format) responses#destroy
register /register(.:format) users#new
login /login(.:format) sessions#new
/offerings(.:format) offerings#index
/needs(.:format) needs#index
dashboard /dashboard(.:format) dashboard#index
contact /contact(.:format) contact#index
your_offerings /your_offerings(.:format) offerings#your_offerings
your_needs /your_needs(.:format) needs#your_needs
search /search(.:format) offerings#search
logout DELETE /logout(.:format) sessions#destroy
-- Original question
This should work for your form_for
<%= form_for([#response, #reply], :url => response_reply_path do |f| %>
-- Second part of your question route matches {:action=>"show", :controller=>"replies"}
I don't see anything wrong in your code, it's maybe in a part of your code you did not paste? Try to search for a link_to that would be corresponding
-- Bonus
Also you should not need to write your render with local variables, the controller instance variables #response and #reply will automatically be present in your partial
<%= render 'replies/reply_form' %>
# #response and #reply are automatically forwarded to all your views and partials
Off course if you are using response and reply in your partial you can rename them to #response and #reply respectively
This is what I've used with remote_form_tag:
<% form_remote_tag(:url => {:controller => '/companies', :action => 'update'},
:update => 'tags') do %>
<%= text_field :company, :tag_list %>
<%= submit_tag 'Save' %>
<% end %>
This is in a Company.view, where Company is a model that is acts_as_taggable_on enabled.
My expectation is that, via ajax, a post is made to companies/10/update
But, instead, what is posted is:
http://localhost:3000/companies/10
and the response is:
No action responded to 10. Actions: create, destroy, edit, email_this_week, index, new, show, and update
This is the update method in CompaniesController:
def update
#company = Company.find(params[:id])
if request.xhr?
# add the given tag to the company
#company.tags << params[:company][:taglist]
#company.save
render :partial => 'tags'
else
if #company.update_attributes(params[:company])
flash[:notice] = "Successfully updated company."
redirect_to #company
else
render :action => 'edit'
end
end
end
Help...?
DELETE /companies/:company_id/contacts/:id(.:forma
{:controller=>"contacts", :action=>"destroy"}
companies GET /companies(.:format)
{:controller=>"companies", :action=>"index"}
POST /companies(.:format)
{:controller=>"companies", :action=>"create"}
new_company GET /companies/new(.:format)
{:controller=>"companies", :action=>"new"}
edit_company GET /companies/:id/edit(.:format)
{:controller=>"companies", :action=>"edit"}
company GET /companies/:id(.:format)
{:controller=>"companies", :action=>"show"}
PUT /companies/:id(.:format)
{:controller=>"companies", :action=>"update"}
DELETE /companies/:id(.:format)
{:controller=>"companies", :action=>"destroy"}
When you update a resource like Company with ID 10, Rails will use the RESTful route:
PUT /companies/10
The PUT method is taken into account when routing your request. Taken from your routes:
PUT /companies/:id(.:format)
{:controller=>"companies", :action=>"update"}
This is correct behaviour for Rails. Just implement the update method in your CompaniesController.
If you require more info on RESTful routes in Rails, check up on this document: http://guides.rubyonrails.org/routing.html