Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-3.2railstutorial.orgsti

Route failing using STI


First SO post, but I've read so many. I'm new to Rails and building first site since studying Hartl's RailsTutorial.

My issue is routing using STI. I believe the routes are set up correctly, but the subclass Kid doesn't find a "show" route.

Class inheritance using STI

class User < ActiveRecord::Base

class Kid < User

Kid Controller

def show

@kid = Kid.find(params[:id])

end

User Controller create

def create
@user = User.new(params[:user])
if @user.save
  flash[:success] = "Welcome to kidtunes!"
  if (@user.type = "Kid")
    ***redirect_to @kid***
  else
redirect_to @parent
  end
else
  render 'new'
end

routes.rb

resources :users, :kids, :parents

root to: 'static_pages#home'

match '/help', to: 'static_pages#help'

match '/contact', to: 'static_pages#contact'

match '/signup', to: 'users#new'

Results in:

kids_new    GET    /kids/new(.:format)         kids#new
  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
   kids     GET    /kids(.:format)             kids#index
            POST   /kids(.:format)             kids#create
new_kid     GET    /kids/new(.:format)         kids#new
   edit_kid GET    /kids/:id/edit(.:format)    kids#edit
    kid     GET    /kids/:id(.:format)         kids#show
            PUT    /kids/:id(.:format)         kids#update
            DELETE /kids/:id(.:format)         kids#destroy
parents     GET    /parents(.:format)          parents#index
            POST   /parents(.:format)          parents#create
 new_parent GET    /parents/new(.:format)      parents#new
edit_parent GET    /parents/:id/edit(.:format) parents#edit
 parent     GET    /parents/:id(.:format)      parents#show
            PUT    /parents/:id(.:format)      parents#update
            DELETE /parents/:id(.:format)      parents#destroy
   root            /                           static_pages#home
   help            /help(.:format)             static_pages#help
contact            /contact(.:format)          static_pages#contact
 signup            /signup(.:format)           users#new

Error I get the following on redirect_to @kid

ActionController::ActionControllerError (Cannot redirect to nil!): app/controllers/users_controller.rb:16:in `create'

I feel like I've checked everything I can check, but I'm still missing something. @kid should properly redirect to the kids#show route. I'm not sure if I have a poorly crafted single table inheritance or a basic routing issue.

thanks in advance. -John

Form

This form is used in users/new.html.erb and it creates the User.

<div class="row">
<div class="span5 offset2">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages' %>

<%= f.label :fname, "First Name" %>
<%= f.text_field :fname %>

<%= f.label :lname, "Last Name" %>
<%= f.text_field :lname %>

<%= f.label :email %>
<%= f.text_field :email %>

<%= f.label :type, "Are you a Kid or Parent?" %>
<%= f.select :type, [['Kid','Kid'],['Parent','Parent']] %>

<%= f.label :password %>
<%= f.password_field :password %>

<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>

<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>


Solution

  • Have you defined/assigned values to the @kid or @parent variables? If not, they will be nil, and you'll get the cannot redirect to nil error you've included in your question.

    Please include the full code for the create action. Otherwise we're left to trust (rather than read for ourselves) precisely what's happening in the redirect.

    Your redirects might also need some work. For example, you could do:

    if (@user.is_a? Kid)
      redirect_to kid_path(@user)
    else
      redirect_to parent_path(@user)
    end
    

    ...or something very similar to that.