2

名前とパスワードの属性を持つ User モデルがあります。ユーザーが [編集] をクリックすると、名前フィールドだけを編集および検証できるようにしたいのですが、パスワード フィールドは編集できません。ユーザーが [パスワードのリセット] をクリックした場合は、その逆です。私の主な問題は、名前フィールドの編集中にパスワードの検証をオフにする方法と、パスワードの編集中に名前の検証をオフにする方法です。

edit.html.erb

<%= form_for @user, html: { class: "form_settings" } do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <p><span><%= f.label :name %></span>
    <%= f.text_field :name %>
  </p>

  <p style="padding-top: 15px"><span>&nbsp;</span>
    <%= f.submit "Submit", class: "submit" %>
  </p>
<% end %>

reset_password.html.erb

<%= form_for @user, html: { class: "form_settings" } do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <p><span><%= label_tag :old_password, "Current Password" %></span>
    <%= password_field_tag :old_password %>
  </p>

  <p><span><%= f.label :password %></span>
    <%= f.password_field :password %>
  </p>

  <p><span><%= f.label :password_confirmation %></span>
    <%= f.password_field :password_confirmation %>
  </p>

  <p style="padding-top: 15px"><span>&nbsp;</span>
    <%= f.submit "Submit", class: "submit" %>
  </p>
<% end %>

users_controller.rb

def update
  @user = User.find(params[:id])
  if params[:old_password]
    if @user.authenticate(params[:old_password])
      @user.update_attributes(password: params[:user][:password])
      flash[:success] = "Password has been updated"
      redirect_to @user
    else
      flash.now[:error] = "Current password is incorrect"
      render :reset_password
    end
  elsif @user.update_attributes(params[:user])
    flash[:success] = "User name updated"
    redirect_to @user
  else
    render :edit
  end
end

私の他の問題は、パスワードと password_confirmation の検証が機能していないことです。これは私がモデルに持っているものです:

validates :password, presence: true, confirmation: true

UPDATE リセットするパスワードと、このコードで動作する検証を取得しました:

def update
  @user = User.find(params[:id])
  if params[:old_password]
    if @user.authenticate(params[:old_password])
      if params[:user][:password] == params[:user][:password_confirmation]
        @user.update_attributes(password: params[:user][:password])
        flash[:success] = "Password has been updated"
        redirect_to @user
      else
        flash.now[:error] = "Passwords don't match"
        render :reset_password
      end
    else
      flash.now[:error] = "Current password is incorrect"
      render :reset_password
    end
  elsif @user.update_attributes(params[:user])
    flash[:success] = "User name updated"
    redirect_to @user
  else
    render :edit
  end
end

しかし、私には複雑すぎるようです。誰でも簡単な解決策を見ますか?

しかし、名前フィールドの編集にはまだ問題があります。パスワードを空白にすることはできないと言っています。

4

3 に答える 3

1

同じアクションで名前の編集とパスワードのリセットを混在させないでください。

ユーザーの属性を更新するアクションを1つ作成します。passwordフィールドは、次のようにホワイトリストに登録しないでください。attr_accessible

パスワードのリセットを処理するもう1つのアクションを作成します。

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    flash[:success] = "User name updated"
    redirect_to @user
  else
    render :edit
  end
end

def reset_password
  if params[:old_password] && @user.authenticate(params[:old_password])
    if params[:user][:password] == params[:user][:password_confirmation]
      @user.password = params[:user][:password]
      flash[:success] = "Password has been updated"
      redirect_to @user
    else
      flash.now[:error] = "Passwords don't match"
      render :reset_password
    end
  else
    flash.now[:error] = "Current password is incorrect"
    render :reset_password
  end
end

このように、各アクションには意味的な役割があります。

ところで、パスワードを保存するためにbcryptのようなものを使用していることを願っています。

于 2013-03-03T13:42:47.870 に答える
1

検証ロジックをモデルに移動し、コントローラーをクリーンに保ちます。

validates :password, presence: true, confirmation: true, if: password?, on: :update
validates :name, presence: true, if: name?, on: :update

これは、レコードを作成するときに必要です。追加するだけon: :create

validates :password, presence: true, confirmation: true, on: :create
validates :name, presence: true, on: :create

コントローラーを次のように変更します。

def update
  @user = User.find(params[:id])
  @user.authenticate(params[:old_password]) if params[:old_password]
  return redirect_to @user, notice: "Sucessfully updated" if @user.update_attributes(params[:user])
  render Rails.application.routes.recognize_path(request.referer)[:action]
end

このリンクから使用されたレンダリングのアイデア: 更新を開始したアクションをレンダリングする

于 2013-03-03T13:32:10.547 に答える
0

それを考え出した...しかし、それはちょっと醜いように見えます:

def update
  @user = User.find(params[:id])
  if params[:old_password]
    if @user.authenticate(params[:old_password])
      if params[:user][:password] == params[:user][:password_confirmation]
        @user.update_attributes(password: params[:user][:password])
        flash[:success] = "Password has been updated"
        redirect_to @user
      else
        flash.now[:error] = "Passwords don't match"
        render :reset_password
      end
    else
      flash.now[:error] = "Current password is incorrect"
      render :reset_password
    end
  elsif params[:user][:name].blank?
    flash[:error] = "Name can't be blank"
    render :edit
  else
    @user.update_attribute(:name, params[:user][:name])
    flash[:success] = "User name updated"
    redirect_to @user
  end
end
于 2013-03-03T03:35:56.767 に答える