2013-01-04 47 views
0

有人可以解釋下面的更新表單的奇怪行爲嗎?Rails更新表單問題?

  • 模型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還含有用腳手架產生的標準表達式

    <%= 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的拋出異常 的ActiveRecord :: RecordNotFound在PostsController#顯示

    找不到郵政使用id = 42

這是怎麼回事嗎?爲什麼這個表述以及爲什麼舊的價值再次被傳遞?

回答

1

好問題是,在你的控制器,你這樣做是:

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

而你傳遞的42於是控制器進入一個ID,並試圖找到一個對象後與42的ID 。但是,沒有ID爲42的Post,所以會引發錯誤。它甚至從來沒有得到你的update_attributes電話,甚至從來沒有去你的驗證。

您必須從此錯誤中拯救,或者使用find_by_id方法,如果未找到記錄,將返回nil

此外,雖然,我想知道,你爲什麼讓你的用戶手動輸入ID?他們不應該知道這一點。這個ID是否應該與主鍵不同?考慮添加一個不同的列,然後像identifierkey或其他的東西,如果是這樣的話就不那麼模棱兩可了。如果你試圖操縱ID(實際上它可能會被Rails所允許),可能會遇到很多問題。

+0

id字段名稱是由事故選擇的,它旨在包含客戶端提供的一些通用數值。現在我看到問題是與標識符衝突。仍在學習。感謝您的解釋。 –

0

update_attributes方法不會更新主鍵或只讀屬性。更多地,update_attributes在更新SQL語句中的WHERE條件中使用id屬性,因此如果更改了id屬性,則最終將更新具有此ID的記錄(或者如果該ID不存在,則根本沒有更新在分貝)。

作爲一種變通方法,你要麼必須自己撰寫最新的SQL語句,或通過與所需的ID創建一個新的記錄(複製舊的屬性和設置一個新的ID),並刪除舊擊中兩次數據庫一。

也就是說,我同意@MrDanA更新主鍵不是一個好主意,我認爲你應該考慮另一種解決問題的方法。