Исключите таблицу соединений в отношениях HasMany в Rails - PullRequest
0 голосов
/ 20 февраля 2010

Я думаю о способах создания системы контроля доступа на основе ролей в Rails. Я тоже видел эти замечательные проекты (среди прочих):

Мой вопрос: действительно ли необходимо иметь объединяющий стол для всего? Если в одной из таблиц отношения есть только несколько значений (скажем, меньше 100), я не могу просто объединить таблицу соединения с этой маленькой таблицей?) Это то, что я имею в виду ... Вот что мне нужно:

Модель

  • Пользователь
  • * Группа 1030 *
  • Роль
  • Разрешение
  • UserRoles / RolesUsers
  • GroupRoles
  • Членство (GroupUsers)
  • RolePermissions

Нечто подобное ...

Способ работы RoleRequirement заключается в создании таблицы roles и таблицы соединения roles_users. Это означает, что если у меня есть 20 возможных ролей в приложении, у меня есть

  • Таблица ролей с 20 строками
  • Таблица RolesUsers с n строками.

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

create_table "roles", :force => true do |t|
  t.string "name"
end

create_table "roles_users", :id => false, :force => true do |t|
  t.integer "role_id"
  t.integer "user_id"
end

с этим ...

create_table "roles", :force => true do |t|
  t.string "name"
  t.integer "user_id" # or some polymorphic form
end

Это может привести к дублированию (например, тонны ролей с именем «admin»), но поскольку пространство дешево, и мы можем создать метод, подобный Role.unique, чтобы найти все уникальные роли (чтобы избавиться от этой таблицы из 20 строк ), почему люди создают таблицу соединений?

То же самое с разрешениями: у меня, вероятно, будет только 4 разрешения для запуска: create read update delete. Поэтому мне не нужны таблица разрешений и таблица role_permissions, я мог бы просто дублировать разрешения CRUD и иметь role_id в таблице разрешений. То же самое с Группой, мне не нужны групповые роли, если в моей таблице roles были полиморфные столбцы.

Каков рекомендуемый способ сделать это?

Вот фрагмент предлагаемой миграции .

1 Ответ

2 голосов
/ 20 февраля 2010

Я бы не советовал вам делать это. То, что вы описываете, называется денормализация .

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

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

Я бы предложил поискать в Google и искать в SO информацию о денормализации. Золотого правила не существует, но у вашего дела нет веских причин для этого.

Если вы ищете повышения производительности, выбросьте ActiveRecord в корзину. Есть много альтернатив, и вы можете написать свой собственный.

...