自定义操作的Rails验证

时间:2012-08-09 11:34:14

标签: ruby-on-rails ruby-on-rails-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 个答案:

答案 0 :(得分:11)

我认为你误解了验证的想法。验证是由模型(通过savecreateupdate)的更改触发的,而不是通过控制器操作触发的,因此在您的操作中没有任何意义让approved操作触发验证的情况。

查看您的代码,在我看来,您真正想要做的是在模型更新时在cat_no上运行验证,条件是{{{ 1}}刚刚成为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 更改为cat_no,则会进行验证,因为nil未更改(因此approved将评估为changed.include?("approved"))。

更有可能这是你真正想要的:

false

答案 1 :(得分:1)

validates语句中指定的:action选项不是控制器操作,而是对模型本身的操作,这是批准控制器操作不会触发模型验证的原因。

在您的情况下,您应该删除验证声明的:on选项:

validates :cat_no, :presence => true

现在模型将在每次保存时验证cat_no是否存在。

答案 2 :(得分: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了解详情。

答案 3 :(得分:1)

试试这个:

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