2014-08-31 2 views
1

Предположим, я создаю модель с простыми характеристиками:(Rails) Как обойти нулевые поля STI?

class CreateWingedThings < ActiveRecord::Migration 
    create_table :winged_things do 
    t.integer :number_of_wings 
    t.integer :species 
    t.integer :air_speed_velocity 
    t.boolean :laden, :default => false 
    end 
end 

Но теперь я хочу два конкретных типов WingedThing, со своими собственными отличными характеристиками:

class CreateBats < ActiveRecord::Migration 
    create_table :bats do 
    t.integer :echolocation_volume 
    t.string :snout_type 
    end 
end 

class CreateBirds < ActiveRecord::Migration 
    create_table :birds do 
    t.string :beak_size 
    t.integer :number_of_feathers 
    end 
end 

Это достаточно простая вещь, чтобы сделать с STI - Иметь Bat и Bird наследуют от WingedThing:

class Bat < WingedThing 

(Бонусный вопрос: как это выглядит в БД? У меня есть строка WingedThing, сгенерированная для каждого Bat и за каждые Bird? Это мое понимание, но, пожалуйста, поправьте меня, если я ошибаюсь.)

(После этого возможно ошибочное понимание) Но что, если бы я хотел, скажем, FlightlessBird? air_speed_velocity было бы бессмысленным полем, и было бы неэтично обременять его; все экземпляры FlightlessBird будут содержать нулевые записи для laden и для air_speed_velocity в строках DB, сгенерированных для соответствующего WingedThing. Это больше данных, чем мне нужно, и не поддается масштабируемости, но я также не хочу полностью удалять поля, так как от них зависят как минимум две другие модели.

Т.Л., д-р Я хотел бы быть в состоянии сделать, это Bird и Bat быть в состоянии получить доступ к характеристикам, общие для обоих, в то время как имеющие FlightlessBirdимеют некоторые характеристики одного и того же родительской таблицы, но без создания нулевые поля в базе данных.

Каков наилучший способ моделирования таких отношений, чтобы убедиться, что я получу самую тонкую БД?

+0

Почему миграция наследуется от 'ActiveRecord :: Base', а не от' ActiveRecord :: Migration'? – mdesantis

+0

Хороший вопрос. Исправлена. – Vardarac

ответ

2

Во-первых, для STI вы не создаете дополнительных таблиц для каждого подкласса - ваши таблицы летучих мышей/птиц не будут использоваться.

Во-вторых, нулевые столбцы, как правило, очень легкие. Например, в postgres их бит-маска для каждой строки, которая говорит, что столбцы являются нулевыми. Битовая маска указывает, какие столбцы присутствуют, поэтому добавление обнуляемым столбец только добавляет 1bit в строке (оставляя в стороне некоторые округлением до тонкостей)

Вы в основном есть 4 варианта:

  • не используют ИППП (т.е. одна таблица на модель, со всеми атрибутами на модель). У вас все еще может быть общий базовый класс (который должен иметь «я».abstract_class = True) для любого общего кода

  • использования ИППП, с некоторыми столбцами неиспользованными для некоторых подклассов

  • использования ИППП, но имеет свои подклассы имеют has_one отношений с таблицей, которая имеет дополнительные столбцы для этого конкретного подкласса

  • сериализовать не являющиеся общие атрибуты (то есть, насколько дб обеспокоен они все имеют одинаковые атрибуты)

Там действителен ча ses для всех этих - у них есть и свои недостатки. Например, если вы спуститесь по пути has_one, который вы можете найти, в зависимости от того, что у вас много запросов к дополнительной таблице. С другой стороны, если вы редко используете дополнительные атрибуты, это здорово.

Я действительно не потел бы несколько нулевых столбцов, хотя вы вряд ли когда-нибудь заметите.

Смежные вопросы