0

更新フォームの次の奇妙な動作を誰かが説明できますか?

  • モデルpost.rbには次の定義が含まれています

    class Post < ActiveRecord::Base
      attr_accessible :id, :name, :content
      validates :id, :presence => true, :numericality => { :greater_than_or_equal_to => 100}, :uniqueness => true 
    end
    
  • コントローラposts_controller.rbは、この方法で更新メソッドを定義します

    class PostsController < ApplicationController
      def update
        @post = Post.find(params[:id])
    
        respond_to do |format|
          if @post.update_attributes(params[:post])
            format.html { redirect_to @post, notice: 'Post was successfully updated.' }
            format.json { head :no_content }
          else
            format.html { render action: "edit" }
            format.json { render json: @post.errors, status: :unprocessable_entity }
          end
        end
      end
    
  • 部分ビュー_form.rbには、scaffoldで生成された標準式も含まれています

    <%= form_for(@post) do |f| %>
      ...
      <div class="field">
        <%= f.label :id %><br />
        <%= f.number_field :id %>
      </div>
      <div class="field">
         <%= f.label :name %><br />
         <%= f.text_field :name %>
      </div>
      <div class="field">
        <%= f.label :content %><br />
        <%= f.text_area :content %>
      </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

問題の説明:

  1. 更新フォームでは、:idの無効な値は42のように指定されます
  2. 検証ヘルパーは無効な入力値(<100)を処理し、「Idは100以上である必要があります」という通知を渡し、データは更新されません
  3. :idのフィールドは、123などの正しい値に置き換えられ、[投稿の更新]ボタンが再度送信されます。
  4. フォームの受信とデータベースの更新の代わりに、Rails はPostsController#showで例外ActiveRecord::RecordNotFoundをスローします

    id=42の投稿が見つかりませんでした

何が起きてる ?なぜ期待と古い値が再び渡されるのですか?

4

2 に答える 2

1

問題は、コントローラーでこれを実行していることです。

@post = Post.find(params[:id])

そして、あなたは42のIDを渡しています。したがって、コントローラーはIDが42のPostオブジェクトを見つけようとします。ただし、IDが42のPostがないため、エラーがスローされます。それはあなたのupdate_attributes電話に届くことさえ決してなく、あなたの検証にさえ決して行きません。

このエラーから救済するか、レコードが見つからない場合find_by_idに返されるメソッドを使用する必要があります。nil

また、なぜユーザーに手作業でIDを入力させているのでしょうか。彼らはそれについて知らないはずです。このIDは主キーとは異なるはずですか?identifierその場合は、またはなどの別の列を追加して、keyあいまいさを少なくすることを検討してください。IDを操作しようとすると、多くの問題が発生する可能性があります(実際には、Railsで許可されている可能性があると考えられます)。

于 2013-01-04T20:10:22.777 に答える
0

update_attributesメソッドは、主キーも読み取り専用属性も更新しません。さらに、SQL更新ステートメントの条件で属性をupdate_attributes使用するため、属性を変更すると、このIDを持つレコードが更新されます(または、IDがデータベースに存在しない場合は更新されません)。 。idWHEREid

回避策として、更新SQLステートメントを自分で作成するか、目的のIDで新しいレコードを作成して(古い属性をコピーして新しいIDを設定)、古いレコードを削除してデータベースに2回アクセスする必要があります。

そうは言っても、私は@MrDanAに同意します。主キーを更新することはあまり良い考えではなく、問題に対する別のアプローチを検討する必要があると思います。

于 2013-01-04T20:38:24.240 に答える