I have the following models: user
, role
, user_role
(user_role
is a join model)
I am trying to edit a user's roles using checkboxes on the user#edit page. Here's my attempt, I feel like I'm missing something significant, or taking the wrong approach.
has_many :user_roles, dependent: :destroy
has_many :roles, through: :user_roles
attr_accessible :user_roles_attributes
accepts_nested_attributes_for :user_roles, reject_if: lambda { |a| a[:role_id] == 0 }, allow_destroy: true
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(user_id: id, role_id: role.id) unless has_role?(role.name.to_sym)
}
end
belongs_to :user
belongs_to :role
delegate :name, to: :role
has_many :user_roles
has_many :users, through: :user_role
def edit
@user = User.find(params[:id])
@user.setup_roles!
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_to edit_user_path(@user)
else
render :edit
end
end
= form_for @user do |f|
= f.fields_for(:user_roles) do |role_form|
= role_form.check_box :role_id, {}, role_form.object.role_id, 0
= role_form.hidden_field :user_id
= role_form.label :name, role_form.object.name
= f.submit 'Update'
However if the :update_only option is true, the nested attributes are used to update the record’s attributes always, regardless of whether the :id is present. The option is ignored for collection associations.
For a one-to-one association, this option allows you to specify how nested attributes are going to be used when an associated record already exists. In general, an existing record may either be updated with the new set of attribute values or be replaced by a wholly new record containing those values.
Allows you to specify the maximum number of associated records that can be processed with the nested attributes. Limit also can be specified as a Proc or a Symbol pointing to a method that should return a number.
If the size of the nested attributes array exceeds the specified limit, NestedAttributes::TooManyRecords exception is raised. If omitted, any number of associations can be processed. Note that the :limit option is only applicable to one-to-many associations.
Here is my solution. I received a lot of help from This Post at RubySource. The way the checkbox is setup, it will destroy a UserRole if "unchecked", and only create it when it is "checked" (why the '0', '1' is on that line.)
def edit
@user = User.find(params[:id])
@user.setup_roles!
end
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(role: role) unless has_role?(role.name.to_sym)
}
end
= form_for @user do |f|
= f.fields_for :user_roles do |builder|
= builder.check_box :_destroy, { checked: builder.object.persisted? }, '0', '1'
= builder.label :_destroy, builder.object.role.name
= builder.hidden_field :role_id
= f.submit 'Update'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With