I am attempting to create an enrollment process similar to SO's:
route to an OpenID provider
provider returns the user's information to the UsersController (a guess)
UsersController creates user, then routes to the ProfilesController's new or edit action.
For now, I'm simply trying to create the user, then route to the ProfilesController's new or edit action (not sure which I should be using).
Here's what I have thus far:
Models:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Routes:
map.resources :users do |user|
user.resource :profile
end
new_user_profile GET /users/:user_id/profile/new(.:format) {:controller=>"profiles", :action=>"new"}
edit_user_profile GET /users/:user_id/profile/edit(.:format) {:controller=>"profiles", :action=>"edit"}
user_profile GET /users/:user_id/profile(.:format) {:controller=>"profiles", :action=>"show"}
PUT /users/:user_id/profile(.:format) {:controller=>"profiles", :action=>"update"}
DELETE /users/:user_id/profile(.:format) {:controller=>"profiles", :action=>"destroy"}
POST /users/:user_id/profile(.:format) {:controller=>"profiles", :action=>"create"}
users GET /users(.:format) {:controller=>"users", :action=>"index"}
POST /users(.:format) {:controller=>"users", :action=>"create"}
new_user GET /users/new(.:format) {:controller=>"users", :action=>"new"}
edit_user GET /users/:id/edit(.:format) {:controller=>"users", :action=>"edit"}
user GET /users/:id(.:format) {:controller=>"users", :action=>"show"}
PUT /users/:id(.:format) {:controller=>"users", :action=>"update"}
DELETE /users/:id(.:format) {:controller=>"users", :action=>"destroy"}
Controllers:
class UsersController < ApplicationController
# generate new-user form
def new
@user = User.new
end
# process new-user-form post
def create
@user = User.new(params[:user])
if @user.save
redirect_to new_user_profile_path(@user)
...
end
end
# generate edit-user form
def edit
@user = User.find(params[:id])
end
# process edit-user-form post
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
format.html { redirect_to(users_path) }
format.xml { head :ok }
...
end
end
end
class ProfilesController < ApplicationController
before_filter :get_user
def get_user
@user = User.find(params[:user_id])
end
# generate new-profile form
def new
@user.profile = Profile.new
@profile = @user.profile
end
# process new-profile-form post
def create
@user.profile = Profile.new(params[:profile])
@profile = @user.profile
respond_to do |format|
if @profile.save
flash[:notice] = 'Profile was successfully created.'
format.html { redirect_to(@profile) }
format.xml { render :xml => @profile, :status => :created, :location => @profile }
...
end
end
end
# generate edit-profile form
def edit
@profile = @user.profile
end
# generate edit-profile-form post
def update
@profile = @user.profile
respond_to do |format|
if @profile.update_attributes(params[:profile])
flash[:notice] = 'Profile was successfully updated.'
# format.html { redirect_to(@profile) }
format.html { redirect_to(user_profile(@user)) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @profile.errors, :status => :unprocessable_entity }
end
end
end
Edit-User View:
...
<% form_for(@user) do |f| %>
...
New-Profile View:
...
<% form_for([@user,@profile]) do |f| %>
..
I'm having two problems:
When saving an edit to the User model, the UsersController attempts to route to http://localhost:3000/users/1/profile.%23%3Cprofile:0x10438e3e8%3E, instead of http://localhost:3000/users/1/profile
When the new-profile form is being rendered, it throws an error that reads: undefined method `user_profiles_path' for #
Is it better to create a blank profile when the user is created (in the UsersController), then edit it OR follow the rest-ful convention of creating the profile in the ProfilesController (as I have done)?
What am I missing?
I did review Associating Two Models in Rails (user and profile), but it didn't address my needs.
Thanks for your time.