I’m almost finished with a sign-up process where:
- (Step 1) New User completes a small form, creating both a User and Profile
- (Step 2) New User is redirected to ProfilesController to fill in the rest of the profile
- (Step 3) New User completes Profile, and is redirected to their Profile
Yet something isn’t working right. I believe what I’ve done is made it so that a Profile is created in both steps 1 and 2 of the above. (Sort of like this post, but my methods are different.)
Can anyone help me fix this?
Here is my code.
ProfilesController:
def new
@profile = Profile.new(params[:profile])
end
def show
@user = User.find(params[:id])
@profile = @user.profile
@superlative = @profile.superlatives.new
end
def edit
@profile = user.profile
end
UsersController:
def new
@user = User.new
@user.profile = Profile.new
if logged_in?
redirect_to current_user.profile
end
end
def create
@user = User.new(params[:user])
if @user.save
session[:user_id] = @user.id
redirect_to signup_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
def edit
@user = current_user
end
def update
@user = current_user
if @user.update_attributes(params[:email])
redirect_to profile_path
else
render :action => 'edit'
end
end
Routes.rb:
match "/signup" => "profiles#edit", :as => "signup"
post "/profiles/new" => "profiles#create"
match "skip/signup", :to => "info#signupskip"
match "skip/profiles/new", :to => "profiles#newskip"
get "/profiles/:id" => "profiles#show", :as => "profile"
get "profiles/new"
root :to => "users#new"
resources :users do
resources :profiles
end
Form #1 (Users#new form):
<%= form_for(@user, :html => {:multipart => true, :id => 'homesign'}) do |f| %>
<%= f.hidden_field :id %>
<%= f.label :email %>
<%= f.text_field :email, :size => 38 %>
<%= f.fields_for :profile do |profile| %>
<div id="name">
<%= profile.label :first_name %>
<%= profile.text_field :first_name, :size => 18 %>
</div>
<% end %>
Form #2 (Profiles#new) form:
<%= form_for '@user.profile', :html => { :multipart => true } do |f| %>
<%= f.hidden_field :id %>
<table id="signupTable">
<tbody>
<tr>
<td class="label"><%= f.label :gender, "Gender:" %></td>
</tr>
<tbody>
</table>
<% end %>
If I use the above, I get “Couldn’t find User with ID=xx”
If I change the above route from:
match "/signup" => "profiles#new", :as => "signup"
To:
match "/signup" => "profiles#edit", :as => "signup"
I get “Couldn’t find User without an ID”
From rake routes:
profiles_show GET /profiles/show(.:format) {:action=>"show", :controller=>"profiles"}
profile GET /profiles/:id(.:format) {:action=>"show", :controller=>"profiles"}
profiles_new GET /profiles/new(.:format) {:action=>"new", :controller=>"profiles"}
POST /profiles/new(.:format) {:action=>"create", :controller=>"profiles"}
profile GET /profiles/:id(.:format) {:action=>"show", :controller=>"profiles"}
user_profiles GET /users/:user_id/profiles(.:format) {:action=>"index", :controller=>"profiles"}
POST /users/:user_id/profiles(.:format) {:action=>"create", :controller=>"profiles"}
new_user_profile GET /users/:user_id/profiles/new(.:format) {:action=>"new", :controller=>"profiles"}
edit_user_profile GET /users/:user_id/profiles/:id/edit(.:format) {:action=>"edit", :controller=>"profiles"}
user_profile GET /users/:user_id/profiles/:id(.:format) {:action=>"show", :controller=>"profiles"}
PUT /users/:user_id/profiles/:id(.:format) {:action=>"update", :controller=>"profiles"}
DELETE /users/:user_id/profiles/:id(.:format) {:action=>"destroy", :controller=>"profiles"}
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
I also have the following routes for signup:
signup_index GET /signup(.:format) {:action=>"index", :controller=>"signup"}
POST /signup(.:format) {:action=>"create", :controller=>"signup"}
new_signup GET /signup/new(.:format) {:action=>"new", :controller=>"signup"}
edit_signup GET /signup/:id/edit(.:format) {:action=>"edit", :controller=>"signup"}
GET /signup/:id(.:format) {:action=>"show", :controller=>"signup"}
PUT /signup/:id(.:format) {:action=>"update", :controller=>"signup"}
DELETE /signup/:id(.:format) {:action=>"destroy", :controller=>"signup"}
UPDATE: rake routes with just resources: users, resources :profiles, and root.
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
new_user GET /users/new(.:format) {:action=>"new", :controller=>"users"}
edit_user GET /users/:id/edit(.:format) {:action=>"edit", :controller=>"users"}
user GET /users/:id(.:format) {:action=>"show", :controller=>"users"}
PUT /users/:id(.:format) {:action=>"update", :controller=>"users"}
DELETE /users/:id(.:format) {:action=>"destroy", :controller=>"users"}
profiles GET /profiles(.:format) {:action=>"index", :controller=>"profiles"}
POST /profiles(.:format) {:action=>"create", :controller=>"profiles"}
new_profile GET /profiles/new(.:format) {:action=>"new", :controller=>"profiles"}
edit_profile GET /profiles/:id/edit(.:format) {:action=>"edit", :controller=>"profiles"}
profile GET /profiles/:id(.:format) {:action=>"show", :controller=>"profiles"}
PUT /profiles/:id(.:format) {:action=>"update", :controller=>"profiles"}
DELETE /profiles/:id(.:format) {:action=>"destroy", :controller=>"profiles"}
root /(.:format) {:action=>"new", :controller=>"users"}
Are you using accepts_nested_attributes_for in your user model? At the very least, it might clean up your code. But, anyway, I believe the problem is with your routes. In addition to reading through this code, I suggest you run a “rake routes” in your application root to make sure that the routes you’re trying to use actually exist.
Update: For your particular codebase, here’s what you need to do.
Use these routes in your routes.rb:
You also need to change:
redirect_to profile_pathtoredirect_to @user.profileredirect_to signup_path ...toredirect_to edit_profile_path(@user.profile)Here is what I usually do with users and profiles, might help:
Scaffolds (just for context):
routes.rb:
controllers/users_controller.rb:
models/profile.rb:
models/user.rb:
users/_form.html.erb:
Using this kind of process flow, somebody can create a user and a profile, and the only form values for profile which will be filled in are ones that you specify defaults for or those that appear in the fields_for block. I think that what you were trying to do isn’t overly complicated, but I think you may have been approaching in the wrong way with regards to your routing.
Cheers