избегая дублирования кода в моделях Rails 3 - PullRequest
1 голос
/ 30 ноября 2011

Я работаю над приложением Rails 3.1, где в базе данных хранится множество различных enum-подобных моделей.В этих моделях много идентичного кода, а также в связанных контроллерах и представлениях.Я решил дублирование кода для контроллеров и представлений через общий класс родительских контроллеров и новое наследование представления / компоновки, которое является частью 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, но весь код, который яВы видели, что для этого предполагается, что у вас не будет подклассов вашего непостоянного класса, которые do сохраняются.

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

1 Ответ

2 голосов
/ 30 ноября 2011

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

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

...