Creating form_for for atributes User image and des

2019-09-21 05:48发布

问题:

I have a rails application with devise, and I added to users a profile image, and a description. What I want to do is to create a page (DIFFERENT of the default registration/edit) where the users, after logged in, can set only this two atributes(image and description).

        <%= form_for(:user, html: { method: :put, :multipart => true })) do |f| %>
         <div class="form-group">
           <%= f.label :Profile_Image %>
           <%= f.file_field :image, class: "form-control" %>
         </div>
         <div class="form-group"> 
          <%= f.label :Descrição %>
            <%= f.text_area :description, class: "form-control", rows: "10" %>
         </div>
        <% end %>

I have already tried two different controllers and none of them worked:

def edit
end

def edit
  @user = User.find(params[:id])
end

My config -> routes are:

get "edit" => "pages#edit"
post "edit" => "pages#edit"

But when i click submit it does nothing! I am new at rails and I am trying to figure this out for hours... How can I create a page to update only the image and the description? Thanks

回答1:

You need an update method in your controller. Your edit method allows the form to render, but you need something like this:

def update
   current_user.update(user_params)
end

Then you would have another method in your controller called user_params, which would look something like this. I was taught to put it under a private heading.

private
   def user_params
     params.require(:user).permit(:profile_image, :description)
   end

I believe there is a shortcut way of including your params with your update method, but this will do.



回答2:

  1. Use registration controller devise and you should customize it.
  2. You should have one method with the same name in one controller, you have two edit method. Change one edit method to update method ( reference : Allow users to edit their account )

    pages_controller.rb

    class PagesController < Devise::RegistrationsController
    
    def edit
     @user = current_user
    end
    
    def update
     @user = current_user
    
     successfully_updated = if needs_password?(@user, params)
       @user.update_with_password(devise_parameter_sanitizer.for(:account_update))
     else
       params[:user].delete(:current_password)
       @user.update_with_password(devise_parameter_sanitizer.for(:account_update))
     end
    
     if successfully_updated
      set_flash_message :notice, :updated
      # Sign in the user bypassing validation in case his password changed
      sign_in @user, :bypass => true
      redirect_to after_update_path_for(@user)
     else
      render "edit"
     end
    end
    
    private
    def needs_password?(user, params)
      user.email != params[:user][:email] || params[:user][:password].present?
    end
    end
    

    application_controller.rb

    class ApplicationController < ActionController::Base
    protect_from_forgery with: :exception
    
    before_filter :configure_permitted_parameters, if: :devise_controller?
    
    def configure_permitted_parameters
      devise_parameter_sanitizer.for(:account_update) do |u|
        u.permit(:description, :image, :email, :password, :password_confirmation)
      end
    end
    end
    
  3. You have wrong http verb (post), you need PUT/PATCH not POST

    devise_scope :user do
     get "edit" => "pages#edit"
     put "update" => "pages#update"
    end
    
  4. On your view looks like (example and not tested)

    <%= form_for(@user, :url => update_pages_path, :html => { :method => :put }) do |f| %>
      <%= devise_error_messages! %>
      <div class="form-group">
        <%= f.label :image, "Profile Image" %>
        <%= f.file_field :image, class: "form-control" %>
      </div>
      <div class="form-group"> 
        <%= f.label description, "Descrição" %>
        <%= f.text_area :description, class: "form-control", rows: "10" %>
      </div>
     <% end %>
    <%= f.submit "Save Image" %>