как определить / прикрепить рельсы валидации в нескольких поколениях модулей - PullRequest
1 голос
/ 02 декабря 2010

Я нашел способ сделать эту работу, но мне интересно узнать о лучшем способе / способе Rails 3.(Я все еще использую 2.3.5, но надеюсь перейти на новый год.)

Ситуация: у меня есть два уровня наследования модулей, второй слой смешивается с моделью Rails.Оба модуля определяют методы проверки, и мне бы хотелось, чтобы они оба прикрепили проверки к базовому классу, но из-за двух уровней наследования следующее не работает:

def self.included(base)
  base.validate :yadda_yadda
end

Когда этот модульвключен другим модулем, интерпретатор останавливается, потому что модули не знают о ActiveRecord::Validations.Включение модуля валидации напрашивается на вопрос "где находится save?"спасибо alias_method.

Следующие работы, если вы помните, чтобы вызывать super всякий раз, когда вы переопределяете validate().Я не доверяю себе или будущим сопровождающим помнить об этом, поэтому я хотел бы использовать вместо этого идиому validate :yadda_yadda, если это возможно.

module Grandpa

  def validate
    must_be_ok
  end

  def must_be_ok
    errors.add_to_base("#{self} wasn't ok")
  end

end

module Dad

  include Grandpa

  def validate
    super
    must_be_ok_too
  end

  def must_be_ok_too
    errors.add_to_base("#{self} wasn't ok either")
  end

end

class Kid  < ActiveRecord::Base

  include Dad

  validate :must_be_ok_three

  def must_be_ok_three
    errors.add_to_base("#{self} wasn't ok furthermore")
  end

end

Предложения?Советы по подходу Rails 3?Я не думаю, что API валидации сильно изменился.

1 Ответ

0 голосов
/ 17 декабря 2010

Я решил это (когда столкнулся с той же проблемой, но с чем-то, кроме проверки).

Краткий ответ: вы можете вызвать send (: includes, base) для модуля, который вы хотите ввестиВ рамках определения включенного выше () вам необходимо проверить, является ли база классом или модулем.

Зачем вам это вообще нужно?Ну, у меня есть несколько модулей, которые извлекают некоторые общие функции из моих моделей.Например, модуль HasAllocable устанавливает полиморфное отношение belongs_to и пару получатель / установщик для виртуального атрибута.Теперь у меня есть еще один модуль, который нужно добавить в HasAllocable, чтобы избавить базовые классы от необходимости его запоминать.Я не видел ничего подобного в Интернете, поэтому мне интересно, является ли несколько уровней наследования моделей больше антипаттерном.

module Grandpa

  def self.included(base)
    if base.kind_of?(Class)
      base.validate :must_be_ok
    end
  end

end

module Dad

  include Grandpa

  def self.included(base)
    if base.kind_of?(Class)
      # you can do this
      #base.send(:include, Grandpa)
      # you can also do this
      Grandpa.send(:included, base)
      # this does not invoke Grandpa.included(Kid)
      #super(base)

      base.validate :must_be_ok_too
    end
  end

end

class Kid  < ActiveRecord::Base
  include Dad
  validate :must_be_ok_three
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...