7

私の知る限り、これはリソースを編集および更新するための標準的な Rails パターンです。

edit アクションの GET ルートと/users/:id/edit、 update アクションの PUT ルートと PATCH ルートの両方があり/users/:idます。

これが私のコントローラーアクションです:

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

def update
  @user = User.find params[:id]

  if @user.update_attributes(user_params)
    redirect_to @user, success: "Changes saved"
  else
    flash.now.alert = "Unable to change account details"
    render :edit
  end
end

そして、フォームのパーシャルでデフォルトの form_for を使用しています:

<%= form_for @user do |f| %>

これは、html で次のフォームを作成しています。

<form accept-charset="UTF-8" action="/users/1" id="edit_user_1" method="post">
  ...
  <input name="_method" type="hidden" value="patch">

への呼び出しがupdate_attributes成功すると、ユーザーは正しくリダイレ​​クトされますが、(ActiveRecord の検証が原因で) 呼び出しが失敗すると、render アクションは編集ビューを正しく表示しますが、ユーザーのブラウザーのパスは から に変更さ/users/1/edit/users/1ます。

私が読んだことから、これはレールの予想される動作であるように見えますが、REST の背後にあるコアのアイデアは、URL がリソースの正規のビューを参照することであると思っていたので、混乱しているように見えますか?

代わりにredirect_to編集アクションを実行するとrender、URLは本来あるべきものになりますが、フォームのエラーメッセージが失われます。

redirect_to を使用する前にエラーをセッションにダンプするよりも、URL とエラー メッセージを永続化する賢明な方法はありますか? できれば避けたいところです。

アップデート:

URL を保持したい理由 (およびエラー) は、current_page? を使用しているためです。ナビゲーションでアクティブな状態を設定します。したがって、フォームがエラーで送信された場合、メニューの「編集」アクションは強調表示されなくなります。

4

2 に答える 2

1

あなたがいた理由は、ビューがではなく/users/1によってレンダリングされるためです。#update#edit

デフォルトでは、リソースのパスは#updateと同じですが#show、リクエスト メソッドGETとが異なりPUTます。したがって、 が#updateHTML レスポンスをレンダリングするときは、 と同じ#showです。

結果にどのようなパスが期待されていても、結果は許容できると思います。すでにわかっているように、 を使用するredirectと、@userインスタンスが新しいブランチに変更されるため、エラーと以前の入力が失われます。

セッションを使用してインスタンス変数を渡すなどのパス上の回避策がありますが、努力する価値はないと思います。現在の結果は十分です。

追加

アクティブ状態の操作は簡単です。current_page?あまりにも多くのコードが必要なのが好きではありません。代わりにcontroller_pathandを使用してください。action_name

  if controller_path == 'users' && (action_name == 'edit' || 'update') 
     # add active class
  end      
于 2013-09-04T13:35:50.867 に答える