У меня есть следующие классы, которые имеют много общего кода с небольшими вариациями.Извлечение общего кода ActiveRecord для аналогичных кланов
class ThirdPartyComponent < ActiveRecord::Base
belongs_to :prev_version, :class_name => 'ThirdPartyComponent', :foreign_key => 'prev_version_id'
has_one :next_version, :class_name => 'ThirdPartyComponent', :foreign_key => 'prev_version_id'
attr_accessible :name, :version, :installer, :install_script
mount_uploader :installer, ComponentFileUploader
mount_uploader :install_script, ComponentFileUploader
validates :name, :presence => true
validates :version, :presence => true, :format => { :with => /\A\d{1,3}\.\d{1,2}\z/ }
validates :installer, :presence => true
validates :install_script, :presence => true
validate :increased_version
def increased_version
# Check to ensure that version number is greater than the previous version number for the same component set
unless prev_version.nil?
version > prev_version.version
end
end
def all_previous_versions
prev_versions = all_versions
prev_versions.shift
prev_versions
end
def all_versions
current_version = self
all_versions = [current_version]
while !current_version.prev_version.nil?
all_versions << current_version.prev_version
current_version = current_version.prev_version
end
all_versions
end
end
class RegistryComponent < ActiveRecord::Base
belongs_to :prev_version, :class_name => 'RegistryComponent', :foreign_key => 'prev_version_id'
has_one :next_version, :class_name => 'RegistryComponent', :foreign_key => 'prev_version_id'
attr_accessible :name, :version, :registry_file
mount_uploader :registry_file, ComponentFileUploader
validates :name, :presence => true
validates :version, :presence => true, :format => { :with => /\A\d{1,3}\.\d{1,2}\z/ }
validates :registry_file, :presence => true
validate :increased_version
def increased_version
# Check to ensure that version number is greater than the previous version number for the same component set
unless prev_version.nil?
version > prev_version.version
end
end
def all_previous_versions
prev_versions = all_versions
prev_versions.shift
prev_versions
end
def all_versions
current_version = self
all_versions = [current_version]
while !current_version.prev_version.nil?
all_versions << current_version.prev_version
current_version = current_version.prev_version
end
all_versions
end
end
Я также рассматриваю возможность добавления некоторых других компонентов в будущем, опять же с очень похожими функциональными возможностями.
Я хочу извлечь общий код из этих классов в один файл (включая вызовы метода ActiveRecord, такие как проверки и т. Д.), А затем просто ссылаться на них в конкретных классах.
До сих пор я пытался,
- наследование - Я создал базовый класс, унаследованный от ActiveRecord, а затем каждый класс, унаследованный от базового класса. Результат: Rails жаловался, что не удалось найти таблицу базы данных, имя которой соответствует базовому классу.
- наследство - я считал создание базового класса в качестве бестабличных моделей вместо (см http://railscasts.com/episodes/219-active-model), но потом я понял, что конкретные классы также будут отсутствовать полную функциональность ActiveRecord
композиция - Я попытался определением общего кода в модуле а затем использовать включить или расширить в конкретных классах для доступа к нему, как показано ниже.
module ComponentBase belongs_to :prev_version, :class_name => self.class.name, :foreign_key => 'prev_version_id' has_one :next_version, :class_name => self.class.name, :foreign_key => 'prev_version_id' attr_accessible :name, :version validates :name, :presence => true validates :version, :presence => true, :format => { :with => /\A\d{1,3}\.\d{1,2}\z/ } validate :increased_version def increased_version # Check to ensure that version number is greater than the previous version number for the same component set unless prev_version.nil? version > prev_version.version end end def all_previous_versions prev_versions = all_versions prev_versions.shift prev_versions end def all_versions current_version = self all_versions = [current_version] while !current_version.prev_version.nil? all_versions << current_version.prev_version current_version = current_version.prev_version end all_versions end end class RegistryComponent < ActiveRecord::Base include ComponentBase attr_accessible :registry_file mount_uploader :registry_file, ComponentFileUploader validates :registry_file, :presence => true end
Это привело к ошибке, что метод
belongs_to
не определен дляComponentBase
. Это выглядит наиболее перспективным решением, но есть ли способ выполнить методы класса ActiveRecord в контексте класса, который включает их? В качестве альтернативы, есть ли лучший способ для меня достичь тех же целей?
Посмотрите мой комментарий к ответу ниже – richard