Problem editing/filling out form for newly created profile
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", :control开发者_运维百科ler=>"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:
resources :profiles
resources :users
root :to => "users#new"
You also need to change:
redirect_to profile_path
to redirect_to @user.profile
redirect_to signup_path ...
to redirect_to edit_profile_path(@user.profile)
Here is what I usually do with users and profiles, might help:
Scaffolds (just for context):
rails generate scaffold User username:string password:string
rails generate scaffold Profile user_id:integer email_address:string website:string
routes.rb:
resources :profiles
resources :users
controllers/users_controller.rb:
class UsersController < ApplicationController
...
# GET /users/new
def new
@user = User.new
@profile = Profile.new
respond_to do |format|
format.html
format.xml { render :xml => @user }
end
end
# GET /users/1/edit
def edit
@user = User.find(params[:id])
@profile = @user.profile.nil? ? Profile.new : @user.profile
respond_to do |format|
format.html
format.xml { render :xml => @user }
end
end
# POST /users
def create
if params[:user][:profile]
profile = params[:venue][:profile]
params[:user].delete(:profile)
params[:user].update({ :profile_attributes => profile })
end
@user = User.find(params[:id])
respond_to do |format|
if @user.save
format.html { redirect_to :action => (@user.profile.nil? ? @user : @user.profile) }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
# PUT /users/1
def update
if params[:user][:profile]
profile = params[:venue][:profile]
params[:user].delete(:profile)
params[:user].update({ :profile_attributes => profile })
end
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
format.html { redirect_to :action => (@user.profile.nil? ? @user : @user.profile) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
...
end
models/profile.rb:
class Profile < ActiveRecord::Base
belongs_to :user
end
models/user.rb:
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
end
users/_form.html.erb:
<%= form_for(@user) do |f| %>
...
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<%= f.fields_for @profile, :profile do |ff| %>
<div class="field">
<%= ff.label :email_address %><br />
<%= ff.text_field :email_address %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
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
精彩评论