Лучший способ хранить константы, на которые есть ссылки в БД? - PullRequest
7 голосов
/ 23 сентября 2008

В моей базе данных у меня есть модель, у которой есть поле, которое должно быть выбрано из одного из списка опций. В качестве примера рассмотрим модель, в которой необходимо хранить измерения, например, 5 футов, или 13 см, или 12,24 м3. Очевидный способ добиться этого - иметь десятичное поле, а затем другое поле для хранения единицы измерения.

Итак, как лучше всего хранить единицы измерения? Я использовал несколько подходов в прошлом:

1) Сохранение различных опций в другой таблице БД (и связанной модели) и связывание этих двух параметров со стандартным внешним ключом (и обычно стремящимся загрузить связанную модель). Это кажется излишним, поскольку вы заставляете БД выполнять объединение для каждого запроса.

2) Хранение опций в виде постоянного хэша, загруженного в один из инициализаторов, где ключ в хэше хранится в поле единиц измерения. Таким образом, вы эффективно выполняете объединение в Ruby (что может увеличивать или не увеличивать производительность), но вы теряете возможность запроса со стороны «единицы измерения». Это не будет проблемой при условии, что вам вряд ли понадобятся запросы типа «найди мне все измерения с единицами см».

Ничто из этого не кажется мне особенно элегантным ... Кто-нибудь может предложить что-то лучше?

Ответы [ 4 ]

6 голосов
/ 23 сентября 2008

Вы видели constant_cache ? Это своего рода комбинация лучших из 1 и 2 - данные поиска хранятся в БД, но отображаются в виде констант класса в модели поиска и загружаются только при запуске приложения, поэтому вы не будете постоянно подвергаться штрафам за соединение. Следующий пример взят из README:

миграция:

create_table :account_statuses do |t|
  t.string :name, :description
end

AccountStatus.create!(:name => 'Active',   :description => 'Active user account')
AccountStatus.create!(:name => 'Pending',  :description => 'Pending user account')
AccountStatus.create!(:name => 'Disabled', :description => 'Disabled user account')

Модель:

class AccountStatus < ActiveRecord::Base
  caches_constants
end

используя его:

Account.new(:username => 'preagan', :status => AccountStatus::PENDING)
3 голосов
/ 23 сентября 2008

Я бы выбрал первый вариант. Насколько большим будет таблица UnitOfMeasurement? И если вы используете целочисленный первичный ключ, почему вы так беспокоитесь о скорости?

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

1 голос
/ 23 сентября 2008

ActiveRecord уже получил поддержку натуральных ключей? Если это так, вы можете просто сделать столбец name (или любой другой) таблицы UnitOfMeasure PK, таким образом, значение столбца FK будет содержать всю необходимую информацию, и у вас все еще будет полностью нормализованная БД с канонический набор значений UnitOfMeasurement.

0 голосов
/ 23 сентября 2008

Вам нужно выполнить поиск по этим значениям? Если нет, вы также можете сохранить их как строку и позже проанализировать строку в приложении, которое считывает значения. В то время как вы рискуете хранить непонятные данные, вы получаете скорость и снижаете сложность БД. Иногда нормализация базы данных не помогает. В конце концов / что-то / в вашей системе должно знать, что «см» - это мера длины, а «м3» - это мера помещения, и сравнение «3 см» с «1 м3» в любом случае не имеет смысла. Таким образом, вы также можете поместить все эти знания в код.

Допустим, вы все равно будете отображать эти данные, что здесь хорошо для нормализации?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...