2012-08-09 96 views
2

我知道你可以這樣做:Rails的驗證

validates :cat_no, :presence => true, :on => :create 

我有一個自定義操作:

def approve 
    @product = Product.find(params[:id]) 
    @product.update_attribute :approved, true 
    redirect_to product_path(@product) 
end 

,我想這樣做:

validates :cat_no, :presence => true, :on => :approve 

這似乎沒有工作。有沒有一個簡單的方法來做到這一點?

回答

10

我認爲你誤解了驗證的想法。驗證通過對模型(通過save,createupdate)的更改觸發,而不是由控制器操作引起的,因此在您的情況下讓approved操作觸發驗證沒有任何意義。在你的代碼

看,在我看來,你真正想要做的是運行一個驗證上cat_no當模特是更新,條件是的approved值剛剛成爲true(即2號線你的approve行動,你有@product.update_attribute :approved, true)。

我認爲下面的代碼應該做到這一點:

validates :cat_no, :presence => true, :on => :update, :if => :just_approved? 

def just_approved? 
    changed.include?("approved") && approved? 
end 

UPDATE:

回想起來,上面的驗證,可能比你實際上會希望有什麼更多的寬容。如果您有一個批准的記錄,並且您將cat_no更改爲nil,它將被驗證,因爲approved尚未更改(所以changed.include?("approved")將評估爲false)。

更可能的,這是你真正想要的東西:

validates :cat_no, :presence => true, :on => :update, :if => :approved? 
+0

啊,這更有意義了。我現在嘗試你的建議代碼。非常感謝 – Raoot 2012-08-09 12:22:32

+0

沒問題,請讓我知道它是否有效。 – 2012-08-09 12:23:44

+0

可悲的是,似乎沒有工作。它仍然讓我對一個缺少產品的產品設置爲true。cat_no – Raoot 2012-08-09 12:45:21

1

validates語句中指定的action選項不是控制器操作,而是模型本身的操作,這就是批准控制器操作不會觸發模型驗證的原因。

,你應該在你的情況做的是去除:在您的驗證聲明選項:

validates :cat_no, :presence => true 

現在,該模型將驗證cat_no每次被保存的時間是存在的。

1

雖然目前尚不清楚,看來你要使用的控制器的Active Record驗證這不應該是這樣。您可以使用ActionController的過濾器,而不是這是很容易做到:

class FooController < ApplicationController 
    before_filter :cat_no, :only => :approve 

    def approve 
    # your approve action code goes here. 
    end 

    private 
    def cat_no 
    #implement your 'validation' here. 
    end 

end 

看看在ActionController Filters guide以獲得更多信息。

0

試試這個:

validates_presence_of :cat_no, on: :approve 

def approve 
    @product = Product.find(params[:id]) 
    @product.attributes = product_params 
    @product.save(context: :approve) 
    redirect_to @product 
end 

private 

def product_params 
    params.require(:product).permit(:name, :description, :cat_no) 
end