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操作的第 2 行@product.update_attribute :approved, true)。

我认为下面的代码应该实现这一点:

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

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

更新:

回想起来,上面的验证可能比你真正想要的更宽松。如果您有一个批准的记录并且您更改cat_nonil,它将验证,因为approved没有更改(因此changed.include?("approved")将评估为false)。

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

validates :cat_no, :presence => true, :on => :update, :if => :approved?
于 2012-08-09T12:01:04.760 回答
1

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

在您的情况下,您应该做的是删除 :on 验证语句的选项:

validates :cat_no, :presence => true

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

于 2012-08-09T11:58:26.860 回答
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 过滤器指南以获取更多信息。

于 2012-08-09T12:03:05.190 回答
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
于 2017-01-26T09:26:49.053 回答