我知道你可以这样做:
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
这似乎不起作用。有一种简单的方法吗?
答案 0 :(得分:11)
我认为你误解了验证的想法。验证是由模型(通过save
,create
或update
)的更改触发的,而不是通过控制器操作触发的,因此在您的操作中没有任何意义让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