Reputation: 1139
the main objective here is to allow each role of users to view and edit only some fields of other users. But roles will be in constant growth, so it needs to be dynamic.
I'm having trouble creating a new role listing all user's field even if the relationship doesn't exists yet.
I would like this:
<%= form.fields_for :role_assignment do |role_assignment_form| %>
<tr>
<td><%= role_assignment_form.text_field :user_field, disabled: true %></td>
<td><%= role_assignment_form.check_box :show_permission, id: :role_show_permission %></td>
<td><%= role_assignment_form.check_box :edit_permission, id: :role_edit_permission %></td>
</tr>
<% end %>
To load like this:
User.attribute_names.map do |att|
role.role_assignment.find_by_user_field(att) || RoleAssignment.new(role: @role,user_field: att)
end
What is shown is only the current registers. I don't even know where to put the code above...
Database diagrams for Role
and RoleAssignment
:
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(12) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(12) | NO | PRI | NULL | auto_increment |
| id_role | int(12) | NO | | NULL | |
| user_field | varchar(255) | NO | | NULL | |
| show_permission | tinyint(1) | NO | | 0 | |
| edit_permission | tinyint(1) | NO | | 0 | |
+-----------------+--------------+------+-----+---------+----------------+
Models:
class Role < ApplicationRecord
self.table_name = "role"
has_many :user_role, foreign_key: :id_role
has_many :user, through: :user_role
has_many :role_assignment, foreign_key: :id_role
accepts_nested_attributes_for :role_assignment, :reject_if => :all_blank, :allow_destroy => true
end
class RoleAssignment < ApplicationRecord
self.table_name = "role_assignment"
belongs_to :role, foreign_key: :id_role
end
Thank you very much.
Upvotes: 0
Views: 73
Reputation: 1139
@fongfan999's train of thought have helped a lot! But this is the complete answer for the specific question:
/app/controllers/roles_controller.rb
:
class RolesController < ApplicationController
def edit
role_assignment = @role.role_assignment
blacklist_attributes = %w(encrypted_password email_token forgot_token token provider uid oauth_token oauth_expires_at)
user_attributes = User.attribute_names - blacklist_attributes
(user_attributes - role_assignment.pluck(:user_field)).each do |user_field|
@role.role_assignment << RoleAssignment.new(user_field: user_field)
end
end
end
/app/views/roles/_form.html.erb
:
<%= form_with(model: role, local: true) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :role_name %>
</div>
<% unless role.new_record? %>
<div class="field">
<table>
<tr>
<th>Field</th>
<th>Show?</th>
<th>Edit?</th>
</tr>
<%= form.fields_for :role_assignment do |role_assignment_form| %>
<tr>
<td><%= role_assignment_form.text_field :user_field, disabled: true %></td>
<td><%= role_assignment_form.check_box :show_permission, id: :role_show_permission %></td>
<td><%= role_assignment_form.check_box :edit_permission, id: :role_edit_permission %></td>
</tr>
<% end %>
</table>
</div>
<% end %>
<br>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Then I have redirected the save button to the edit form:
format.html { redirect_to edit_role_path(@role), notice: 'Role was successfully created now you can edit the permissions.' }
And the user experience is like this:
Then:
Thank you everyone for helping me solve it.
Upvotes: 0
Reputation: 2624
Try to the following:
# app/controllers/roles_controller.rb
role_assignment = @role.role_assignment
# You might not show these attributes, right?
blacklist_attributes = %w(id created_at updated_at)
user_attributes = User.attribute_names - blacklist_attributes
# Do not build existing user fields
(user_attributes - role_assignment.pluck(:user_field)).each do |user_field|
@role.role_assignment.build(user_field: user_field)
end
Should we use role_assignments
(plural form) instead of role_assignment
(singular form) in :has_many
?
Upvotes: 1