Как настроить 2 псевдонимных отношения has_and_belong_to_many с одним классом? - PullRequest
0 голосов
/ 27 апреля 2020

Я разрабатываю механизм авторизации на основе атрибутов и управления доступом на основе ролей. Мне нужно связать роли для группы (пользователей) и доступные функции для группы (пользователей). Ни класс Role, ни класс Feature не существуют, они определяются как списки опций, извлеченных из класса Parameter. Подводя итог, я пытаюсь создать 2 отношения HABTM между классом Parameter и классом Group.

Отношения встроены в форму редактирования ролей. Вот мой код:

  <div class="row mat-form-row">
    <div class="mat-form-field col-md-6">
      <%= f.label :roles, t('Roles'), class: "mat-form-field-label" %>
      <%= f.collection_select :role_ids, list_of_user_roles, :id, :name, { }, { multiple: true, class: "mat-input-element select2-candidate" } %>
    </div>
    <div class="mat-form-field col-md-6">
      <%= f.label :feature, t('Features'), class: "mat-form-field-label" %>
      <%= f.collection_select :feature_ids, list_of_app_features, :id, :name, { }, { multiple: true, class: "mat-input-element select2-candidate" } %>
    </div>
  </div>
</div>

, где list_of_users_roles и list_of_app_features извлекаются из таблицы параметров.

Была создана таблица ссылок со структурой по умолчанию для хранения nn-ассоциаций:

class CreateTableGroupsParameters < ActiveRecord::Migration[5.2]
  def change
    create_table "groups_parameters", id: :serial do |t|
      t.references :parameter, index: true
      t.references :group,  index: true
      t.boolean "is_active",                       default: true,  comment: "As nothing can be deleted, flags objects removed from the knowledge base"
      t.datetime "active_from",                    default: -> { 'current_date' }, comment: "Validity period"
      t.datetime "active_to"
      t.timestamps
    end
  end
end

Модели были связаны и установлены надежные параметры:

##group.rb
  has_and_belongs_to_many :roles, :class_name => "Parameter"
  has_and_belongs_to_many :features, :class_name => "Parameter"

##parameter.rb
  has_and_belongs_to_many :groups

##groups_controller
    # Never trust parameters from the scary internet, only allow the white list through.
    def group_params
      params.require(:group).permit(:name, :description, :role, :territory_id, :organisation_id, :created_by, :updated_by, :code, :role_ids => [], :feature_ids => [])
    end

Создание ссылки успешны для каждого из отношений в отдельности, будь то роли или функции. Но когда оба реализованы вместе, обновление одного списка значений работает только. Хуже того, обновление другого удаляет предыдущее обновление!

У вас есть предложение, чтобы решить эту проблему? Большое спасибо!

1 Ответ

0 голосов
/ 29 апреля 2020

Благодаря Beartech, который попросил более подробную информацию, я понял, что проблема может быть более сложной, чем неправильное понимание синтаксиса с моей стороны. На самом деле, консоль показывает, что управление этими списками значений подразумевает удаление каждого списка нежелательных записей в объединяемой таблице. Учитывая поведение по умолчанию для метода has_and_belong_to_many , я использовал имя по умолчанию для таблицы соединений и таким образом создал только одну таблицу. Имея два отношения, используя свою таблицу, второе удаляет то, что было установлено первым.

Решение состоит в том, чтобы создать 2 отдельные таблицы для поддержки двух отношений и указать каждому вызову метода has_and_belongs_to_many, какую таблицу использовать :

class CreateTablesGroupsParameters < ActiveRecord::Migration[5.2]
  def change
    create_table "groups_roles", id: :serial do |t|
      t.references :parameter, index: true
      t.references :group,  index: true
      t.boolean "is_active",                       default: true,  comment: "As nothing can be deleted, flags objects removed from the knowledge base"
      t.datetime "active_from",                    default: -> { 'current_date' }, comment: "Validity period"
      t.datetime "active_to"
      t.timestamps
    end
    create_table "groups_features", id: :serial do |t|
      t.references :parameter, index: true
      t.references :group,  index: true
      t.boolean "is_active",                       default: true,  comment: "As nothing can be deleted, flags objects removed from the knowledge base"
      t.datetime "active_from",                    default: -> { 'current_date' }, comment: "Validity period"
      t.datetime "active_to"
      t.timestamps
    end
  end
end

И в модели:

 ##group.rb
  has_and_belongs_to_many :roles, :class_name => "Parameter", :join_table => "groups_roles"
  has_and_belongs_to_many :features, :class_name => "Parameter", :join_table => "groups_features"

Спасибо за поддержку в этом поиске решения.

...