3

私はあなたができることを知っています:

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

これはうまくいかないようです。これを行う簡単な方法はありますか?

4

4 に答える 4

11

検証の考え方を誤解していると思います。検証は、コントローラーのアクションではなく、モデルへの変更によって (またはを介し​​てsave)トリガーされるため、アクションで検証をトリガーすることは意味がありません。createupdateapproved

あなたのコードを見ると、あなたが本当にやりたいことはcat_no、モデルが更新されたときに検証を実行することのようapprovedに思えtrueます。approve@product.update_attribute :approved, true

以下のコードはそれを達成するはずだと思います:

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

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

アップデート:

振り返ってみると、上記の検証は、おそらく実際に必要なものよりも寛大です。承認済みのレコードがあり、 に変更cat_noするとnil、 が変更されていないため検証approvedされます (したがって、changed.include?("approved")に評価されfalseます)。

おそらくこれはあなたが実際に望んでいるものです:

validates :cat_no, :presence => true, :on => :update, :if => :approved?
于 2012-08-09T12:01:04.760 に答える
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 ガイドをご覧ください。

于 2012-08-09T12:03:05.190 に答える
1

validates ステートメントで指定された :action オプションはコントローラー アクションではなく、モデル自体に対するアクションです。これが、コントローラーの承認アクションがモデルの検証をトリガーしない理由です。

あなたのケースですべきことは、検証ステートメントの :on オプションを削除することです:

validates :cat_no, :presence => true

これで、モデルは保存されるたびに cat_no が存在することを検証します。

于 2012-08-09T11:58:26.860 に答える