父属性验证ActiveRecord

时间:2011-01-13 09:49:23

标签: ruby-on-rails validation activerecord parent

例如,我有模型文章。文章有一篇文章内容。 ArticleContent默认验证其所有属性。但我还需要其他功能 - 保存草稿文章,无需任何验证。 所以我通过了:draft => false作为Article.new()中的一个参数,接下来我做@ article.build_article_content()。 ArticleContent中有一些不可用的代码:

  def draft?
    raise self.article.draft
  end

  validates_presence_of :header, :message => "We have no fuckin' header!", :unless => :draft?

当然不行。在选秀时?执行没有任何合适的Article对象,所以self.article返回nil。不错的尝试,codemonkey ......

任何人都有一些甜蜜的想法?我想要@ content.save!不是一个好主意

更新

我试过了:

def draft
    self[:draft]
end

def draft=(value)
    self[:draft] = value
end

def draft?
    self[:draft]
end

validates_presence_of :field1, :message => "msg1", :unless => :draft?
validates_presence_of :field2, :message => "msg2", :unless => :draft?
validates_presence_of :field3, :message => "msg3", :unless => :draft?

它有效,但我该如何分组?

unless self.draft?
    validates_presence_of :field1, :message => "msg1"
    validates_presence_of :field2, :message => "msg2"
    validates_presence_of :field3, :message => "msg3"
end

说那个选秀?找不到方法。我也应该这样做

@article.content.draft = @article.draft

它看起来像脏兮兮的黑客

1 个答案:

答案 0 :(得分:2)

这是状态机的常见用例。有几个导轨插件可以提供这些。

http://ruby-toolbox.com/categories/state_machines.html

如果您不需要完整的状态机实现,那么在ArticleContent模型中拥有状态列仍然是有益的。它的价值观将是“新”,“草稿”,“公布”等等。在确定要执行的操作时,您的验证将查看该列的值,例如:

validates :content, :presence => true, :unless => Proc.new { |a| a.state == "Draft" }

(我很确定这不是正确的语法,但你应该得到我的目标。)

回答您的更新

尝试with_options。

with_options :unless => :draft? do |o|
    o.validates_presence_of :field1, :message => "msg1"
    o.validates_presence_of :field2, :message => "msg2"
    o.validates_presence_of :field3, :message => "msg3"
end

看看你的代码有几个气味。为了避免验证,要做的事情是errors.add(blah),而不是引发异常。此外,为访问草稿列而定义的方法看起来有点多余。他们正在做AR所做的事情。