ActiveRecord::RecordNotFound -- Couldn't find User without an ID
controller, ruby-on-rails
Solution
The error is telling you that in this line:
@profile = @user.profile.build
@user.profile is nil.
Since you haven't created the profile yet, this makes sense. Instead, go for something like this.
@profile = Profile.new(:user_id => @user.id)
Re: The index page throwing an exception.
You are defining @users in your controller, and then referencing @user in your path helpers. Also, iterating over @users should give you User objects, not Profile objects.
It looks like you're trying to use the Profile#index action to show a list of users. That's kind-of OK, in a not-quite-pure-REST way. However, I would expect to see something more like this.
<% @users.each do |user| -%>
<% unless user.profile.blank? -%>
<%= h user.profile.name %>
<%= h user.profile.category %>
<%= link_to 'Go to profile', user_profile_path(user, user.profile) %>
<% end -%>
<% end -%>
Problem
Please see UPDATES at the bottom of the question... For reference, this problem evolved out of some fixes I made based on a previous problem I was having here: Associating Two Models in Rails (user and profile) I'm building an app that has a user model and a profile model. I want to associate these models such that: - After the user creates an account, he is automatically sent to the "create profile" page, and the profile he creates is connected to only that particular user. - Only the user who owns the profile can edit it. I generated the user model using nifty_generators. When the user hits submit for the account creation, I redirect him to the "new profile" view to create a profile. I did this by editing the redirect path in the user controller. The user controller looks like this: ``` def new @user = User.new end def create @user = User.new(params[:user]) if @user.save session[:user_id] = @user.id flash[:notice] = "Thank you for signing up! You are now logged in." redirect_to new_user_profile_path(:user_id => @user) else render :action => 'new' end end ``` When I click 'submit' to create a new user, it now sends me to the following url, which seems right: localhost:3000/users/6/profile/new. But it throws the following exception: NoMethodError in ProfilesController#new You have a nil object when you didn't expect it! The error occurred while evaluating nil.build The trace indicates that the problem is in the profiles controller, in the New method. The profiles controller looks like this: ``` def index @user = User.find(params[:user_id]) @profile = @user.profile(:order => "created_at DESC") end def show @user = User.find(params[:user_id]) @profile = @user.profile.find(params[:id]) end def new @user = User.find(params[:user_id]) @profile = @user.profile.build end def edit @user = User.find(params[:user_id]) @profile = @user.profile.find(params[:id]) end def create @user = User.find(params[:user_id]) @profile = @user.profile.build(params[:profile]) if @profile.save flash[:notice] = 'Profile was successfully created.' redirect_to(@profile) else flash[:notice] = 'Error. Something went wrong.' render :action => "new" end end ``` Additionally, the app also throws an exception when I try to view the index page of the profiles (there are currently no profiles because I can't get past the user creation step to create one). This is the exception: ActiveRecord::RecordNotFound in ProfilesController#index Couldn't find User without an ID This is what the log is telling me: Processing ProfilesController#index [GET] Parameters: {"action"=>"index", "controller"=>"profiles"} ActiveRecord::RecordNotFound (Couldn't find User without an ID): app/controllers/profiles_controller.rb:5:in `index' To give you the rest of the details on the app, the models have the following associations: Profile belongs _to :user User has _one :profile I have this in the routes.rb file: map.resources :users, :has_one => :profile In the view for the new profile page that's throwing the first exception listed above, I have this: ``` <% form_for([@user, @profile]) do |f| %> <%= f.error_messages %> .... <% end %> ``` In the view for the profile index that's throwing the second exception explained above, I have this: ``` <% @profiles.each do |profile| %> <div class="post"> <div class="left"> <p>Store: </p> <p>Category: </p> </div> <div class="right"> <p><%=h profile.name %></p> <p><%=h profile.category %></p> </div> <div class="bottom"> <p><%= link_to 'Go to profile', user_profile_path(@user, profile) %></p> <p><%= link_to 'Edit', edit_user_profile_path(@user, profile) %></p> <p><%= link_to 'Destroy', user_profile_path(@user, profile), :confirm => 'Are you sure?', :method => :delete %></p> </div> ``` I've spent hours trying to track down the problem myself as a learning exercise, but at this point I have no idea how to fix this. Appreciate the help! UPDATE: jdl, per your request: profiles/new.html.erb: ``` <% form_for([@user, @profile]) do |f| %> <%= f.error_messages %> <div class="left"> <p> <%= f.label :name %><br /> <%= f.text_field :name %>required </p> <p> <%= f.label :category %><br /> <%= f.text_field :category %>required </p> <p> <%= f.label :address1 %><br /> <%= f.text_field :address1 %> </p> <p> <%= f.label :address2 %><br /> <%= f.text_field :address2 %> </p> <p> <%= f.label :city %><br /> <%= f.text_field :city %> </p> <p> <%= f.label :state %><br /> <%= f.text_field :state %> </p> <p> <%= f.label :zip %><br /> <%= f.text_field :zip %>required </p> <p> <%= f.label :phone %><br /> <%= f.text_field :phone %> </p> <p> <%= f.label :email %><br /> <%= f.text_field :email %> </p> </div> <div class="right"> <p> <%= f.label :website %><br /> <%= f.text_field :website %> </p> <p> <%= f.label :description %><br /> <%= f.text_area :description %> </p> </div> <p> <%= f.submit 'Create' %> </p> <% end %> ``` routes.rb: ActionController::Routing::Routes.draw do |map| map.signup 'signup', :controller => 'users', :action => 'new' map.logout 'logout', :controller => 'sessions', :action => 'destroy' map.login 'login', :controller => 'sessions', :action => 'new' map.resources :sessions ``` map.resources :users, :has_one => :profile map.root :controller => "home" map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end ``` PROFILES CONTROLLER (as of 8/20/09, 8pm EST) class ProfilesController < ApplicationController ``` def index @users = User.all(:order => "created_at DESC") end def show @user = User.find(params[:user_id]) end def new @user.profile = Profile.new end def edit @user = User.find(params[:user_id]) @profile = @user.profile.find(params[:id]) end def create @user = User.find(params[:user_id]) @profile = @user.profile.build(params[:profile]) if @profile.save flash[:notice] = 'Profile was successfully created.' redirect_to(@profile) else flash[:notice] = 'Error. Something went wrong.' render :action => "new" end end def update @profile = Profile.find(params[:id]) if @profile.update_attributes(params[:profile]) flash[:notice] = 'Profile was successfully updated.' redirect_to(@profile) else render :action => "edit" end end def destroy @profile = Profile.find(params[:id]) @profile.destroy redirect_to(profiles_url) end end ``` Cody, the index page below is throwing the following exception: NoMethodError in Profiles#index Showing app/views/profiles/index.html.erb where line #14 raised: undefined method `name' for # ``` <div id="posts"> <% @users.each do |profile| %> <div class="post"> <div class="left"> <p>Store: </p> <p>Category: </p> </div> <div class="right"> <p><%=h profile.name %></p> <p><%=h profile.category %></p> </div> <div class="bottom"> <p><%= link_to 'Go to profile', user_profile_path(@user, profile) %></p> <p><%= link_to 'Edit', edit_user_profile_path(@user, profile) %></p> <p><%= link_to 'Destroy', user_profile_path(@user, profile), :confirm => 'Are you sure?', :method => :delete %></p> </div> </div> ```