Pergunta

I installed Carrierwave and followed the instructions to get it working so that users could upload an image/avatar. My avatar_uploader.rb looks normal, I haven't really changed anything.

class AvatarUploader < CarrierWave::Uploader::Base

  storage :file

  def store_dir
    "/images/"
  end

  version :thumb do
    process :scale => [50, 50]
  end

  def extension_white_list
    %w(jpg jpeg png)
  end

end

I added the image tag to the user edit part of the site (_form.html.erb), since it is a part of the users.

  <%= image_tag(@user.avatar_url) if @user.avatar? %>
  <p><%= f.file_field :avatar %></p>
  <%= f.hidden_field :avatar_cache %>

and to the show.html.erb:

<%= avatar_tag user.avatar_url(:thumb) if @user.avatar? %>

My users_controller.rb update function I haven't done much to change.

def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

and in this, the user_params seems okay.

   def user_params
      params.require(:user).permit(:username, :email, :full_name, :password, :password_confirmation, :avatar)
    end

When I try to update the user (i.e. upload a file) with the edit page, it gives me an error

undefined method `update' for nil:NilClass

and points to the if @user.update part of my users_controller file. It also seems to be taking in "id"=>"username" as a parameter. I have a vanity URL using my routes.rb file

get "/:username", to: "users#show", as: "username"

but when I click the update user button, it redirects back to /users/username. I'm not sure if this is causing it or if I didn't implement the avatar upload correctly. I feel like I'm missing something simple here.

Edit: My routes.rb file looks as follows root 'home#index'

  get "users/new"
  get "/about" => "static_pages#about"
  get "/contact" => "static_pages#contact"
  get "/signedout" => "sessions#signout"

  post "login" => "sessions#login"

  resources :posts
  resources :users
  resources :sessions, only: [:new, :login, :signout]

  match '/signin',    to: 'sessions#login',    via: 'get'
  match '/signup',    to: 'users#new',         via: 'get'
  match '/signedout', to: 'sessions#signout',  via: 'delete'

  get "/:username",    to: "users#show",       as: "username"

It's also showing the following Request parameters:

Request

Parameters:

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"C2bHFQkNIjZ090wZhN4bLTJAl7Jqw4ZmRwyo3cmOQ5s=",
 "user"=>{"username"=>"jsamson",
 "email"=>"me@jsamson.com",
 "full_name"=>"Jesse Samson",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]",
 "avatar_cache"=>""},
 "commit"=>"Update User",
 "id"=>"jsamson"}
Foi útil?

Solução

You need to define an instance of User in your users#update controller action:

# app/controllers/users_controller.rb
def update
  @user = User.find(params[:id]) # Insert this as the first line of the method
  # remainder of code
end

As-is, your code is throwing an undefined method 'update' for nil:NilClass because @user is nil, and thus has no update method. Assigning the correct instance of User to the @user instance variable will resolve this issue.

UPDATE:

According to the request parameters cited in the question, the form is posting a username as the id parameter. In order to handle this, you'll want to retrieve the User by finding the record with the username matching the params[:id]:

def update
  User.find_by_username(params[:id])
end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top