0

I am developping an authorisations maganement, based on Attributes and Roles Based Access Control. I need to associate Roles to a Group (of users), and available Features to a Group (of users). Neither the Role class nor the Feature class exist, they are defined as lists of of options extracted from the Parameter class. To summarize, I try to create 2 HABTM relations betweenthe Parameter class and the Group class .

The relations are built in the roles edit form. Here is my code:

  <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>

where list_of_users_roles and list_of_app_features are extracted from the parameters table.

A link table was created with default structure to store the n-n associations :

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

Models have been linked and strong parameters set up:

##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

Creatin the links is successfull for each of the relations separately, either roles, or features. But when both are implemented toghether, updating one list of values only works. Worst, updating the other one erases the previous update!

Do you have a suggestion to solve this? Thanks a lot!

user1185081
  • 1,898
  • 2
  • 21
  • 46
  • 1
    Please show the web server console messages for when you submit the form both ways. It will show what is being submitted and how it is structures so we can compare them. – Beartech Apr 28 '20 at 00:57
  • 1
    "the feature works fine..." is completely vague. Please read the question guidelines here https://stackoverflow.com/help/how-to-ask . It helps if you describe the issue as if we know nothing about your app, because we don't! LOL or imagine describing tying your shoes to a person who cannot see. i.e very detailed and simple. – Beartech Apr 28 '20 at 01:00

1 Answers1

0

Thanks to Beartech who asked for more details, I realised the issue may be more complex than a syntax misunderstanding from my side. Actually, the console reveals that managing these lists of values implies for each list deleteting the content of unwanted records in the join table. Considering the default behaviour for the has_and_belong_to_many method I used the default naming the join table, and thus created only one table. Having two relations using his table, the second one deletes what was set by the first one.

The solution is to create 2 seperate tables to support the 2 relations, and specify to each has_and_belongs_to_many method call which table to use:

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

And in the model:

 ##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"

Thanks for supporting me in this search for a solution.

user1185081
  • 1,898
  • 2
  • 21
  • 46