私は次のクラスを定義しています。これらのクラスには、マイナーなバリエーションを含む多くの共通コードがあります。
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
また、非常によく似た機能を持つ他のコンポーネントを将来的に追加することも検討しています。
これらのクラスから共通のコードを単一のファイル (validate などの 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 クラス メソッドを実行する方法はありますか? あるいは、同じ目的を達成するためのより良い方法はありますか?