0

I want to update a Profile model attribute by using link_to. The Profile model have a lang column, and I want to change to :en.

I could find out that I should use method: :put.

<%= link_to t('english'), profile_path(profile: {lang: :en}), method: :put %>

But it's ends up with error:

ActionController::UrlGenerationError in StaticPages#home
Showing /Users/ironsand/dev/phrasebook/app/views/layouts/_header.html.erb where line #21 raised:

No route matches {:action=>"update", :controller=>"profiles", :profile=>{:lang=>:en}} missing required keys: [:id]

I have this line in routes.rb to use the path:

resources :profiles, only: :update

How can I enable the function like this?

I found a similar question, but the case is a bit difference.

Edit

class ProfilesController < ApplicationController
  def update
    return redirect_to root_path unless current_user # If user is not logged in, redirect to /
    if current_user.profile.update(profile_params) # Don't forget about validation for lang in Profile model
      redirect_to root_path
    else
      redirect_to root_path
    end
  end
  private
  def profile_params
    params.require(:profile).permit(:lang)
  end
end
Community
  • 1
  • 1
ironsand
  • 14,329
  • 17
  • 83
  • 176

2 Answers2

1

You need to identify the profile somehow, that's why it asks for id. But you can update profile without id, you just need to improve update method:

def update
  return redirect_to root_path unless current_user # If user is not logged in, redirect to /

  if current_user.profile.update(profile_params) # Don't forget about validation for lang in Profile model
    redirect_to success_path
  else
    redirect_to error_path
  end
end

private

def profile_params
  params.require(:profile).permit(:lang)
end

For route, try this:

resources :profiles, only: [] do
  collection do
    put :update
  end
end

or just:

put '/profiles' => 'profiles#update'
Jeiwan
  • 954
  • 6
  • 13
  • Thanks, but I got a error `param is missing or the value is empty: profile` in the line ` params.require(:profile).permit(:lang)`. – ironsand Dec 06 '15 at 05:42
  • 1
    Did you change the link? Check logs for this request and look for "Parameters: ..." If there is no `{ profile: { lang: :en }}`, but only `{lang: :en}`, then just remove this part: `.require(:profile)` – Jeiwan Dec 06 '15 at 05:48
  • oh, that was my terrible mistake, and thanks I could do it! – ironsand Dec 06 '15 at 06:21
0

Since you're updating a specific profile, you need to supply something that lets your controller know what profile you're updating.

As you can see from the error message generated, your controller can't identify which profile it is that you're asking to be updated. You need to supply the id of the profile in order to update it.

One way this could be achieved with link_to is as follows:

link_to t('english'), profile_path(id: @profile.id, lang: :en), method: :put

lang would then be available in your update action in params[:lang].

Zajn
  • 4,078
  • 24
  • 39