开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜