You don't need nested attributes to simply assign associations to a record.
To start with you want to alter your tables and associations to create a normalization table:
class User < ApplicationRecord
has_many :user_roles, dependent: :destroy
has_many :roles, through: :user_roles
end
# remove user_id from the roles table
class Role < ApplicationRecord
validates_uniqueness_of :name
has_many :user_roles, dependent: :destroy
has_many :users, through: :user_roles
end
# rails g model user_role user:references role:references
class UserRole < ApplicationRecord
validates_uniqueness_of :role_id, scope: :user_id
belongs_to :user
belongs_to :role
end
This means the definition name of a role is only defined once in the roles table instead of being duplicated for every role applied to a user. And to assign the role to a user you're just adding a role id and user id in a join table which can be indexed much more efficiently.
Since we don't need to set that duplicate name column for every user role we can just use role_ids= to set the roles of a user with a checkbox.
<%= form_for(@user) do |f| %>
<%= f.collection_check_boxes(:role_ids, Role.all, :id, :name) %>
...
<% end %>
class UsersController < ApplicationController
# ...
def create
@user = User.new(user_params)
# ...
end
# ...
private
def user_params
params.require(:user)
.permit(:foo, :bar, role_ids: [])
end
end