Проверка ActiveRecord по родительскому атрибуту

У меня есть модельная статья, например. Статья имеет_один ArticleContent. 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

И это тоже похоже на грязно-грязный хак


person everm1nd    schedule 13.01.2011    source источник
comment
Извините, я только что увидел ваше обновление.   -  person noodl    schedule 15.01.2011


Ответы (1)


Это обычный вариант использования конечного автомата. Есть несколько плагинов для рельсов, которые обеспечивают это.

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 сделала бы в любом случае.

person noodl    schedule 13.01.2011