在行动上进行自定义验证

时间:2011-02-18 13:05:22

标签: ruby-on-rails ruby-on-rails-3 validation state-machine

我想知道是否有办法在自定义操作上使用rails验证。

例如,我想做类似的事情:

validates_presence_of :description, :on => :publish, :message => "can't be blank"

我做基本验证创建和保存,但有很多事情我不想预先要求。即,他们应该能够在不验证所有字段的情况下保存准系统记录,但是我在我的控制器和模型中有一个自定义的“发布”操作和状态,在使用时应验证以确保记录为100%

上面的例子没有用,有什么想法吗?

更新:

我的状态机看起来像这样:

  include ActiveRecord::Transitions
  state_machine do 
    state :draft
    state :active
    state :offline

    event :publish do
      transitions :to => :active, :from => :draft, :on_transition => :do_submit_to_user, :guard => :validates_a_lot?
    end

  end

我发现我可以添加警卫,但我仍然希望能够使用rails验证而不是在自定义方法上完成所有操作。

2 个答案:

答案 0 :(得分:5)

这看起来更像是业务逻辑而不是模型验证。几年前我参与了一个项目,我们不得不发表文章,当时正在执行许多业务规则。

我建议您执行类似Model.publish()的操作,该方法应该强制执行所有业务规则,以便发布项目。

一种选择是运行自定义验证方法,但您可能需要向模型添加一些字段。这是一个例子 - 我假设你的模型被称为文章

Class Article < ActiveRecord::Base
  validate :ready_to_publish

  def publish
    self.published = true
    //and anything else you need to do in order to mark an article as published
  end

  private
  def ready_to_publish
    if( published? ) 
      //checks that all fields are set 
      errors.add(:description, "enter a description") if self.description.blank?
    end
  end
end

在此示例中,客户端代码应调用an_article.publish,并且在调用article.save时,它将自动执行其余操作。这种方法的另一个重大好处是,您的模型将始终保持一致,而不是取决于调用的操作。

答案 1 :(得分:1)

如果您的“发布”操作将某种状态字段设置为“已发布”,那么您可以执行以下操作:

validates_presence_of :description, :if => Proc.new { |a| a.state == 'published' }

或者,如果每个州都有自己的方法

validates_presence_of :description, :if => Proc.new { |a| a.published? }