STI и расширение подклассов для включения «дополнительных» столбцов в базу данных? - PullRequest
2 голосов
/ 08 февраля 2011

Может быть, STI не то, что я хочу, и я открыт для всех предложений, но ради этих вопросов давайте предположим следующую реальную ситуацию:

Вы хотите, чтобы ваше приложение содержало данные APIдля разных поставщиков почты.Используя STI, у вас есть следующие модели

class MailSetting < ActiveRecord::Base
belongs_to :user

end


class MailChimp < MailSetting

end

class AWeber < MailSetting

end

class PostageApp < MailSetting

end

Теперь давайте выполним некоторые действия консоли:


user = User.first
setting = user.create_mail_setting(:type => "MailChimp")

Хорошо, теперь вы хотите добавить настройки ключа API.MailChimp просто использует ключ api_key.Aweber может использовать api_key и подпись, а Postageapp, скажем, использует систему api_key и token.

Вы бы расширили каждый подкласс, чтобы включить в базу данных все необходимые вам столбцы?Не могли бы вы собрать все STI и просто сделать обычные классы, скажем, MailChimp, которые наследуются от AR?

Я пришел к выводу, что STI знает, что у всех моих пользователей будет MailSetting, это тип, который можетрасширяться со временем.Тем не менее, я испытываю боль в расширении этих подклассов таким способом, потому что вы не можете делать такие вещи, как user.mail_setting.connect, не зная, из какого они подкласса, а затем, что мне нужно, чтобы соединить этих парней?

Мысли

Ответы [ 3 ]

3 голосов
/ 09 февраля 2011

Вы должны использовать полиморфные классы вместо STI

UPD

некоторые ссылки:

UPD 2

Представь, нам нужна модель Post. И у нас есть Статья и Тема, которые наследуют от Почты.

rails g model Post title:string body:text content_type:string content_id:integer

То есть title и body являются общими полями для Темы и Статьи. Теперь давайте создадим другие модели с полем user_id в теме и link в статье

rails g model Topic user_id:integer
rails g model Article link:string

Теперь мы будем редактировать модели:

class Post < ActiveRecord::Base
  belongs_to :content, :polymorphic => true, :dependent => :destroy
end

class Topic < ActiveRecord::Base
  has_one :post, :as => :content, :dependent => :destroy
end

class Article < ActiveRecord::Base
  has_one :post, :as => :content, :dependent => :destroy
end

Это может быть довольно сложно, но копайте так:)

2 голосов
/ 05 мая 2015

Вы можете рассмотреть возможность использования метода store_accessor из ActiveRecord::Store.

Подход хранилища STI , приведенный здесь , демонстрирует, как вы можете назначать отдельным подклассам разные средства доступа, которые сериализуются в один столбец суперкласса.

Если вы используете PostgreSQL> = 9.2, тогда это прекрасно работает с его типом JSON, если нет, то вы можете позволить Rails выполнять сериализацию (используя store вместо store_accessor.

TLDR (при условии PostgreSQL> = 9.2):

Добавить миграцию:

add_column :mail_settings, :vendor_settings, :json

Определить соответствующие атрибуты в подклассах:

class MailChimp < MailSetting
    store_accessor :vendor_settings, :api_key
    validates :api_key, presence: true
end 
0 голосов
/ 09 февраля 2011

Мне кажется, что ваша схема достаточно бесформенная, поэтому вам лучше использовать базу данных без схемы.Возможно, одно из решений на основе документов NoSQL?Таким образом, вы можете добавлять и удалять поля в своих записях по своему усмотрению.

...