Newbie working on his first rails application after studying Hartl's Rails Tutorial book & video cast.
I'm using a STI model where:
class User < ActiveRecord::Base
class Kid < User
class Parent < User
User has the basic elements: name, email, etc.
The problem I'm having is with routing. I continue to work in determining which model will ultimately work best in this situation (STI or polymorphic). I've started with STI and I think I can get this to work if I can nail down the routing issues.
My problem is my edit is looking for an "update" action in the users controller when I want it to route to kidupdate I've been reading many SO posts about STI routing but I can't seem to figure out why this won't route correctly.
Rspec test. It the error comes from the "click_button"
describe "with valid information" do
let(:new_first) { "New First" }
let(:new_last) { "New Last" }
let(:new_email) { "[email protected]" }
before do
fill_in "First Name", with: new_first
fill_in "Last Name", with: new_last
fill_in "Email", with: new_email
select "Kid", from: "Are you a Kid or Parent"
fill_in "Password", with: kid.password
fill_in "Confirmation", with: kid.password
click_button "Save changes"
end
Rspec error:
KidPages edit with valid information
Failure/Error: click_button "Save changes"
AbstractController::ActionNotFound:
The action 'update' could not be found for UsersController
# (eval):2:in `click_button'
# ./spec/requests/kids_pages_spec.rb:32:in `block (4 levels) in <top (required)>'
Routes:
root / static_pages#home
help /help(.:format) static_pages#help
contact /contact(.:format) static_pages#contact
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
kidshow /kids/:id(.:format) users#kidshow
kidupate PUT /kids/:id(.:format) users#kidupdate
kidedit /kids/:id/edit(.:format) users#kidedit
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
routes.rb
root to: 'static_pages#home'
match '/help', to: 'static_pages#help'
match '/contact', to: 'static_pages#contact'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match 'kids/:id', to: 'users#kidshow', :as => 'kidshow'
match 'kids/:id', to: 'users#kidupdate', :via => 'put', :as => 'kidupdate'
match 'kids/:id/edit', to: 'users#kidedit', :as => 'kidedit'
resources :users
resources :sessions, only: [:new, :create, :destroy]
I've been struggling with these concepts and this problem for weeks and I appreciate the help.
You can organize your controller better to avoid this issue altogether. See below
routes.rb
resources :kids
resources :parents
This would directly give you named path:
edit_kid_path(kid_id)
edit_parent_path(parent_id)
kids_controller.rb
class KidsController < ApplicationController
def update
end
end
parents_controller.rb
class ParentsController < ApplicationController
def update
end
end
If you want to share controller behavior, You can potentially do
class KidsController < UsersController
end
class ParentsController < UsersController
end
and put the common actions in users_controller.rb and override them in the child controllers.
The decision on what model relationships to use should be independent of how you structure your controllers. Controllers and routing is one area of consideration. Modeling data is entirely separately consideration. And declaring resources are just shortcuts for some matching routes.
If you are not going to use users#update etc, declaring resources :users
is unnecessary as you are not using any of the routes that declaration provides.