Внедрение абстрактного базового модельного класса, Rails Way ™
У меня есть модель Book и Download, в которой есть много атрибутов, поэтому моя цель - наследовать общие атрибуты из модели DownloadableResource.
Посмотрел на STI, но вместо этого я пошел абстрактным способом базовой модели:
-
модели:
class DownloadableResource < ActiveRecord::Base
self.abstract_class = true
attr_accessible :title, :url, :description, :active, :position
validates :title, :url, :description, presence: true
scope :active, where(active: true).order(:position)
end
class Book < DownloadableResource
attr_accessible :cover_url, :authors
validates :cover_url, :authors, presence: true
end
class Download < DownloadableResource
attr_accessible :icon_url
validates :icon_url, presence: true
end
-
миграции:
class CreateDownloadableResources < ActiveRecord::Migration
def change
create_table :downloadable_resources do |t|
t.string :title
t.string :url
t.text :description
t.boolean :active, default: false
t.integer :position
t.timestamps
end
end
end
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.string :cover_url
t.string :authors
t.timestamps
end
end
end
class CreateDownloads < ActiveRecord::Migration
def change
create_table :downloads do |t|
t.string :icon_url
t.timestamps
end
end
end
После миграции, когда я создаю новую книгу, результат далеко не ожидался:
> Book.new
=> #<Book id: nil, cover_url: nil, authors: nil, created_at: nil, updated_at: nil>
Может ли кто-нибудь пролить свет на то, как реализовать метод абстрактного базового модельного класса, поэтому модели ActiveRecord могут совместно использовать общий код через наследование, но сохраняются в разных таблицах базы данных?
Ответы
Ответ 1
Объявляя модель абстрактной, вы на самом деле говорите, что нет базовой таблицы, и вы хотите разрешить подкласс. Это значит:
- Вам не нужна таблица
downloadable_resources
- Book.table_name печатает
books
вместо downloadable_resources
Как уже упоминалось в @Finbarr, это также означает, что обе модели Book
and Download
должны иметь все атрибуты в своих таблицах.
Что это действительно полезно для этого? По-моему, не очень. Вы можете делиться валидациями, областями и т.д., Но вы можете достичь всего этого легче, включив в него настраиваемые модули.
Чтобы решить вашу проблему, я бы, вероятно, пошел с другим подходом. Я бы создал еще одну модель под названием DownloadableContent
которая была бы автономной. Он будет включать проверки, и таблица будет иметь все атрибуты. И, наконец, модели Book
and Download
будут иметь полиморфное отношение has_one
к модели DownloadableContent
.
Вы можете использовать подход STI, но мне вообще не нравится смешивать все пользовательские атрибуты.
Ответ 2
В этом случае не должно быть таблицы downloadable_resources
. Обе таблицы книг и загрузок должны объявлять все поля, в которых они нуждаются.