4

How to map out has_one model with nested routes and how to add a form_for for /localhost:3000/users/1/profile/new,html.erb following RESTful database?

User has one Profile.

Models

class Profile < ActiveRecord::Base
  attr_accessible :name, :surname
  belongs_to :user
end

class User < ActiveRecord::Base
  attr_accessible :email, :email_confirmation, :password, :password_confirmation
  has_secure_password
  has_one :profile, dependent: :destroy
end

  resources :users do
    resources :profiles      (note: has_one profile)
    resources :progress_charts
    resources :calories_journals
  end

views/profiles/new.html.erb

<h1>About You</h1>
<div class="row">
  <div class="span6 offset3">
    <%= form_for(@profile) do |f| %>
    <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :surname %>
      <%= f.text_field :surname %>

      <%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div>

controller: Profiles_controller.rb Two errors I have discovered as I do not quite understand why it wasn't working.

class ProfilesController < ApplicationController
def index
end

def show
end

  def new
  #  @user = User.find(params[:id]) # Error message: Couldn't find User without an ID
  #  @profile = @user.build_profile()

    @profile = current_user.build_profile(params[:id]) # Error message: unknown attributes: user_id
  end

  def edit
  end

  def create
  end

  def update
  end

  def destroy
  end
end

Helpers: SessionHelper (to illustrate current_user) module SessionsHelper def sign_in(user) cookies.permanent[:remember_token] = user.remember_token self.current_user = user end

  def signed_in?
    !current_user.nil?
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user?(user)
    user == current_user
  end

  def current_user
    @current_user ||= User.find_by_remember_token(cookies[:remember_token])
  end

  def sign_out
    self.current_user = nil
    cookies.delete(:remember_token)
  end

  def signed_in_user
    unless signed_in?
      store_location
      redirect_to signin_path, notice: "Please sign in."
    end
  end
end
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
smileymike
  • 253
  • 6
  • 22

1 Answers1

5

Does your profiles table has a user_id attribute?

In your routes, profile should be singular, since a user has one profile:

resources :users do
    resource  :profile
    resources :progress_charts
    resources :calories_journals
end

The route to a user profile will be users/:user_id/profile (and not users/:user_id/profile/:id

In your profiles_controller:

@profile = current_user.build_profile(params[:id]) # why params[:id]?
#it should just be
@profile = current_user.build_profile()
@user = User.find(params[:user_id])

And the form would be something like:

form_for [@user, @profile] do |f|...
end

Do you really want the user to create his profile like that? Usually, you would create the profile when a user register.

Robin
  • 21,667
  • 10
  • 62
  • 85
  • Thanks for reply, originally I thought profile attributes should be User but I found no information regarding one model many forms unlike many articles about nested models in a single form. So I decided to break it up into smaller components such as email * pwd form -> About user -> User Goal. In profile_controller, I get error messages that supposed to work, I am bit stressed out why it doesnt work. See two error messages with hashes. – smileymike Jul 04 '12 at 22:50
  • Simple bug! I edited schema.rb instead of migration rb which causing errors! – smileymike Jul 04 '12 at 23:30
  • 2
    Don't ever edit schema.rb, it's recreated everytime you migrate. If you need to edit your schema, run `rails g migration name_of_the_migration`, and write your changes there. – Robin Jul 05 '12 at 02:52