Reputation: 19
I'm creating a User, Role and UserRole. A user can create a list of roles, and from the new user form, there is a nested form which populate a list of roles created, then the user able to select a role and associated with the new user. I'm able to create a list of roles, but facing problem when creating a nested form in the new user view file.
Here are the models, kindly advise me if relationships are correct.
class User < ApplicationRecord
has_one :user_role
has_one :role, through: :user_role
end
class Role < ApplicationRecord
has_many :user_roles
has_many :users, through: :user_roles
end
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
User
controller. I'm not sure if my controller is correct:
def new
@user = User.find_by_id(params[:id])
@user = @current_user.account.users.new
@user.build_user_role
end
def create
@user = User.find_by_id(params[:id])
@user = @current_user.account.users.create_with_password(user_params)
if @user.save
redirect_to users_path
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:id, :email, :password, :password_confirmation, :admin, :owner, user_role_attributes: [:user_id, :role_id])
end
end
Below is new user form:
<%= form_for(@user, remote: true) do |f| %>
<%= f.text_field :email, class: "form-control", autofocus: true, autocomplete: "off" %>
<%= f.check_box :admin, class:"checkbox" %>
<%= f.check_box :owner, class:"checkbox" %>
<%= f.fields_for :user_role do |ff| %>
<%= ff.collection_select :role_id, @roles, :id, :role_name, include_blank: false %>
<% end %>
<%= f.button "Create", class: "btn btn-success" %>
<% end %>
The nested form for user_role
doesn't show up, and also kindly advise if the relationships between User
, Role
and UserRole
are correct.
Upvotes: 0
Views: 199
Reputation: 102036
If the user only can ever have one role you don't really need the user_roles
join table in the first place:
class User < ApplicationRecord
belongs_to :role
end
class Role < ApplicationRecord
has_many :users
end
Although it seems pretty naive to assume that you won't actually want a many to many association which is actually a lot more useful. Eg:
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles
end
class Role < ApplicationRecord
has_many :user_roles
has_many :users, through: :user_roles
end
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
You're also following into a common beginner trap where you confuse nested attributes with simply selecting an association.
You don't need @user.build_user_role
or f.fields_for :user_role
. You just need a select and to whitelist the role_id
param:
<%= form_for(@user, remote: true) do |f| %>
# ...
<%= f.collection_select :role_id, @roles, :id, :role_name, include_blank: false %>
# ...
<% end %>
def new
# why even do this if you are just reassigning it on the next line?
@user = User.find_by_id(params[:id])
@user = @current_user.account.users.new
end
def create
@user = User.find_by_id(params[:id])
# Violation of Law of Demeter - refactor!
@user = @current_user.account.users.create_with_password(user_params)
if @user.save
redirect_to users_path
else
render 'new'
end
end
private
def user_params
params.require(:user)
.permit(
:id, :email, :password,
:password_confirmation,
:admin, :owner,
:role_id # this is all you really need
)
end
Upvotes: 0