0

(Rails 3を使用)ユーザーとユーザーセッションを管理するためにauthlogicをセットアップしました(ユーザーコントローラーとuser_sessionsコントローラー、および関連するビュー、モデルなどを使用)。管理者とクライアントの 2 つのレベルのユーザーがいます。管理者はユーザーの作成とユーザーの編集を行うことができ、ユーザーは Web サイト上のドキュメントを閲覧することしかできません (ユーザーの編集権限や閲覧権限はまったくありません)。

次に、クライアントが Web サイトでパスワードを変更できるようにする別のコントローラー (reset_password) を実装しました。これを行うために、クライアントがクライアントを編集できるようにしました (クライアントが自分自身を編集できるようにするため)。ただし、クライアントがパスワードを変更できるフォームは、管理者がクライアントを作成できるフォームよりもはるかに制限されています。

私が抱えている問題は、クライアントがパスワード編集フォームに移動し、無効なパスワードまたはパスワードの確認を入力すると、ページが完全な管理フォームに更新され、クライアントが権限を変更できるようになることです。失敗したフォーム入力を強制して、クライアントを管理フォームではなく、直前に表示されていたフォームに戻します。

問題は、管理フォームとクライアント フォームの両方が 'form_for @user do |f|' を使用しているためです。フォームを定義します。レールはこの 2 つを区別できないと思います。

関連ファイルは次のとおりです。

私の管理フォーム (users#edit レンダリングされたフォーム):

= stylesheet_link_tag :universal
= form_for @user do |f|
    - if @user.errors.any?
    #error_explanation
        %span.boldHeader= "#{pluralize(@user.errors.count, "error")} prohibited this user from being saved:"
        %ul
            - @user.errors.full_messages.each do |msg|
                %li= msg

    .fieldContainer
        .field
            = f.label :username
            = f.text_field :username
        .field
            = f.label :role
            = f.collection_select :role, User::ROLES, :to_s, :humanize, { :selected => :client }
    .fieldContainer
        .field
            = f.label :password
            = f.password_field :password
        .field
            = f.label :password_confirmation
            = f.password_field :password_confirmation
    .fieldContainer
         .field
            = f.label :first_name
            = f.text_field :first_name
         .field
            = f.label :last_name
            = f.text_field :last_name
        .field
            = f.label :firm_name
            = f.text_field :firm_name
    .fieldContainer
        .field
            = f.label :email
            = f.text_field :email
        .field
            = f.label :phone 
            = f.text_field :phone
    .actions
        = f.submit 'Save'
        %a.button{ :href => "/users" }Cancel

私のクライアントフォーム(レンダリングされたフォームでreset_password#edit):

= stylesheet_link_tag :universal
= form_for @user do |f|
    - if @user.errors.any?
        #error_explanation
            %span.boldHeader= "#{pluralize(@user.errors.count, "error")} prohibited this user from being saved:"
            %ul
                - @user.errors.full_messages.each do |msg|
                    %li= msg

    .fieldContainer
        .field
            = f.label :password
            = f.password_field :password
        .field
            = f.label :password_confirmation
            = f.password_field :password_confirmation

    .actions
        = f.submit 'Save'
        %a.button{ :href => "/users" }Cancel

クライアント フォームの更新方法:

def update
    @user = current_user
    if @user.update_attributes(params[:user])
        format.html { redirect_to @user, notice: 'Password successfully changed.' }
        format.json { head :no_content }
    else
        format.json { render json: @user.errors, status: :unprocessable_entity }
        format.html { redirect_to "/settings" }
    end
end

管理フォームの更新方法:

  def update
    respond_to do |format|
      if @user.update_attributes(params[:user])
        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

注: /settings は、部分的なレンダリングを含む reset_passwords#edit にルーティングします。これにより、クライアント フォームが表示されます (上記を参照)。また、routes ファイルにはリソースとして users、user_sessions、および reset_passwords があります。

最後に、これが私が生産ログで見ているものです。reset_password/_form (クライアント フォーム) で開始した後、users/_form (管理者フォーム) にロールバックされていることがわかります。

Started GET "/settings" for 127.0.0.1 at 2013-07-02 16:26:52 -0400
Processing by ResetPasswordsController#edit as HTML
  User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Rendered reset_passwords/_form.html.haml (4.0ms)
  Rendered reset_passwords/edit.html.haml within layouts/application (14.0ms)
  Rendered shared/_header.html.haml (1.0ms)
Completed 200 OK in 57ms (Views: 54.0ms | ActiveRecord: 0.0ms)
[2013-07-02 16:26:52] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true


Started GET "/assets/global.css?body=1" for 127.0.0.1 at 2013-07-02 16:26:52 -0400
Served asset /global.css - 304 Not Modified (0ms)
[2013-07-02 16:26:53] WARN  Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true


Started PUT "/users/1" for 127.0.0.1 at 2013-07-02 16:26:58 -0400
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"9KeHrOySL3FRhSnfYtVvKl2rCz9EPBSyGmtGGasDxnA=", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Save", "id"=>"1"}
  User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "1"]]
  User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
   (0.0ms)  begin transaction
  User Exists (0.0ms)  SELECT 1 AS one FROM "users" WHERE ("users"."persistence_token" = '5d1007bf94b34a7de44707e4ca432b18338f1c9ef6c5f99bf04845096a6b880057b5b43c917b9d38f790521ef62147eec3d9302471da73967048b48b4a399b18' AND "users"."id" != 1) LIMIT 1
   (1.0ms)  rollback transaction
  Rendered users/_form.html.haml (9.0ms)
  Rendered users/edit.html.haml within layouts/application (19.0ms)
  Rendered shared/_header.html.haml (0.0ms)
Completed 200 OK in 80ms (Views: 61.0ms | ActiveRecord: 1.0ms)
4

1 に答える 1

0

フォームが取るルートを指定する必要がありました。以前は、「クライアント」フォームでこれを使用していました (reset_password#edit とレンダリングされたフォーム):

= form_for @user do |f|

これを次のように変更しました。

= form_for @user, :url => reset_password_path(@user) do |f|

次に、フォームのコントローラーにもいくつか変更を加えました。

def update
    @user = current_user
    @user.password = params[:user][:password]
    @user.password_confirmation = params[:user][:password_confirmation]
    respond_to do |format|
        if !@user.changed?
            format.html { redirect_to "/settings", notice: 'Form incomplete' }
            format.json { render json: @user.errors, status: :unprocessable_entity }
        elsif @user.save
            format.html { redirect_to "/index", notice: 'Password successfully changed' }
            format.json { head :no_content }
        else
            format.html { redirect_to "/settings", notice: 'Form incomplete' }
            format.json { render json: @user.errors, status: :unprocessable_entity }
        end
    end
end

私が必要としていたのはrespond_to do |format|.

于 2013-07-08T17:30:31.973 に答える