iCyborg
iCyborg

Reputation: 4728

How to edit profile ? (using devise and has a model Profile but edit method is giving error)

I am using devise and has created a model profile.

I have added the has_one relationship to user and belongs_to :user to profile model. I have also added user_id column in profile.

I have also added

before_filter :create_profile
def create_profile 
  profile = Profile.create
end

in User model. When a new user registers it a new profile do gets created. So if the user id is 10, this is what is getting created in profile

#<Profile id: 2, name: nil, created_at: "2013-08-17 06:44:33", updated_at: "2013-08-17 06:47:00", user_id: 10> 

Now the problem is, I have put an edit link in application.rb

<li><%= link_to "Profile".html_safe, edit_profile_path(current_user) %></li>

but it is giving error

Couldn't find Profile with id=10

so instead of searching for id=2, it is looking at user_id, how to fix this ? I am sure I am missing out on something very small but not sure what.

EDIT - the error is coming from this line @profile = Profile.find(params[:id]) in edit method

# profiles_controller.rb
def edit
  @profile = Profile.find(params[:id])
end

I have tried to use :user_id and :profile_id but that also gave error "Couldn't find Profile without an ID"

EDIT 2-

routes.rb has, it is pretty much blank

resources :profiles

rake routes output (the other paths are devise standard paths)

                profiles GET        /profiles(.:format)                                     profiles#index
                         POST       /profiles(.:format)                                     profiles#create
             new_profile GET        /profiles/new(.:format)                                 profiles#new
            edit_profile GET        /profiles/:id/edit(.:format)                            profiles#edit
                 profile GET        /profiles/:id(.:format)                                 profiles#show
                         PUT        /profiles/:id(.:format)                                 profiles#update
                         DELETE     /profiles/:id(.:format)                                 profiles#destroy

profiles_controller.rb , the other 5 methods are standard once

  def edit
    @user = current_user
    @profile = @user.profiles.find(params[:profile_id])

  end

  def create

    @profile = current_user.build_profile(params[:profile])

    respond_to do |format|
      if @profile.save
        format.html { redirect_to @profile, notice: 'User profile was successfully created.' }
        format.json { render json: @profile, status: :created, location: @profile }
      else
        format.html { render action: "new" }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

Upvotes: 0

Views: 5626

Answers (3)

Matthias
Matthias

Reputation: 4375

First fix your user model:

before_filter :create_profile
def create_profile 
  profile = Profile.create
end

should be:

after_create :create_profile

def create_profile
  self.profile.create
end

before_filter is for controllers, not for models!

Second: Change this line

<li><%= link_to "Profile".html_safe, edit_profile_path(current_user) %></li>

to this one:

<li><%= link_to "Profile", edit_profile_path(current_user.profile) %></li>

Third: Change your controller edit action:

def edit
  @profile = current_user.profile
end

I think you could remove the create action from your profiles_controller, because you have the before_create hook in your user model which creates the profile.

Your routes

resources :profiles

just provides you an id parameter for the edit action, and that´s the id from the profile, and not from the user. You could add one through nested routes for the current_user, but that´s not necessary, because you already have the current_user method from devise which returns you the current logged in user.

btw:

"Profile".html_safe 

=> is not necessary.

"<h1>Profile</h1>".html_safe

=> would be necessary.

Upvotes: 2

dax
dax

Reputation: 11007

Not sure what your controller looks like, but you can explicitly tell rails where to find the profile_id. something like this:

<li><%= link_to "Profile".html_safe, edit_profile_path(current_user, profile_id: @profile) %></li>

Edit:
#<Class:0xb459b8c> is the whole user class, not an instance which is why you can't call profiles on it. try this:

@user = current_user
@profile = @user.profiles.find(params[:profile_id])

Edit 2:

According to your original question:

the problem is, I have put an edit link in application.rb

<li><%= link_to "Profile".html_safe, edit_profile_path(current_user) %></li>

but it is giving error

Couldn't find Profile with id=10

so instead of searching for id=2, it is looking at user_id, how to fix this ?

The problem, i think, is here:

`<li><%= link_to "Profile".html_safe, edit_profile_path(current_user) %></li>`

your `edit_profile_path' calls for

/profiles/:id/edit(.:format)

that :id is the :id of the profile table, not the user table - so your link_to should look like this:

<li><%= link_to "Profile".html_safe, edit_profile_path(id: @profile.id) %></li>

or just

<li><%= link_to "Profile".html_safe, edit_profile_path(@profile) %></li>

and your controller should look like this (how it did originally):

# profiles_controller.rb
def edit
  @profile = Profile.find(params[:id])
end

which will give your routes what they want.

Upvotes: 1

Sami
Sami

Reputation: 1051

If devise already provide edit functionality then why you need to maintain profile just for edit still if you need it you should not add user_id column in profile it should come User.

Try this:

<%= link_to "edit", edit_user_registration_path(current_user) %>

Upvotes: 2

Related Questions