избежание дублирования кода в моделях Rails 3

Я работаю над приложением Rails 3.1, в котором в базе данных хранится несколько различных моделей, подобных перечислению. В этих моделях много одинакового кода, а также в связанных с ними контроллерах и представлениях. Я решил проблему дублирования кода для контроллеров и представлений с помощью общего класса родительского контроллера и нового наследования представления/макета, которое является частью Rails 3.

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

class Format < ActiveRecord::Base

  has_and_belongs_to_many :videos

  attr_accessible :name

  validates :name, presence: true, length: { maximum: 20 }

  before_destroy :verify_no_linked_videos

  def verify_no_linked_videos
    unless self.videos.empty?
      self.errors[:base] << "Couldn't delete format with associated videos."
      raise ActiveRecord::RecordInvalid.new self
    end
  end

end

У меня есть четыре или пять других классов с почти идентичным кодом (единственное отличие — объявление ассоциации). Я пытался создать модуль с общим кодом, который они все включают (что похоже на Ruby Way), но большая часть дублирующегося кода зависит от ActiveRecord, поэтому методы, которые я пытаюсь использовать в модуле (validate, attr_accessible и т. д.) недоступны. Я знаю об ActiveModel, но это не совсем то, что нужно.

Я также пытался создать общий непостоянный родительский класс, который является подклассом ActiveRecord::Base, но весь код, который я видел для выполнения этого, предполагает, что у вас не будет подклассов непостоянного класса, которые продолжать упорствовать.

Любые предложения о том, как лучше всего избежать дублирования этих идентичных строк кода во многих разных моделях перечисления?


person Dustin Frazier    schedule 30.11.2011    source источник


Ответы (1)


Я нашел решение для совместного использования кода для моделей Rails 3, поэтому решил поделиться им с другими. Оказывается, в ActiveModel есть все, что мне нужно (по крайней мере, пока). Я создал модуль Enum, используя ActiveSupport::Concern, ActiveModel::Validations и ActiveModel::MassAssignmentSecurity, и включил этот модуль в каждую из своих моделей перечисления:

module Enum

  extend ActiveSupport::Concern

  include ActiveModel::Validations
  include ActiveModel::MassAssignmentSecurity

  included do

    attr_accessible :name

    validates :name, presence: true, length: { maximum: 20 }

    before_destroy :verify_no_linked_videos

    private

    def verify_no_linked_videos
      unless self.videos.empty?
        self.errors[:base] << "Couldn't delete object with associated videos."
        raise ActiveRecord::RecordInvalid.new self
      end
    end

  end

end

То, как команда Rails 3 вытащила код, не относящийся к базе данных, из ActiveRecord в ActiveModel, действительно довольно гладко! Следующие ссылки помогли укрепить мое понимание того, как использовать этот материал:

http://www.fakingfantastic.com/2010/09/20/concerning-yourself-with-active-support-concern/

http://asciicasts.com/episodes/237-dynamic-attr-accessible

person Dustin Frazier    schedule 30.11.2011