Reputation: 909
I am new to Rails 3 and having trouble with saving records in the Join table. I have been looking around and trying different examples found on this website and from the documentation or books, but I don't understand why I can't get it to work. I am trying to create Authorization by creating Roles and associate them to users. So far I have been trying to assign roles from the update action in the Users controller without prevail.
I have 3 models: the User.rb, role.rb, and assignment.rb (the join table)
class User < ActiveRecord::Base
has_many :assignments, :dependent => :destroy
has_many :roles, :through => :assignments, :foreign_key => :role_id
accepts_nested_attributes_for :roles
attr_accessor :password, :role_ids
attr_accessible :first_name, :last_name, :email, :password, :password_confirmation, :status, :description, :username, :roles_attributes
...
end
class Role < ActiveRecord::Base
has_many :assignments
has_many :users, :through => :assignments, :foreign_key => :user_id
accepts_nested_attributes_for :users
attr_accessible :name
end
class Assignment < ActiveRecord::Base
belongs_to :user
belongs_to :role
accepts_nested_attributes_for :roles
end
The Users controller in the update action I have the following
class UsersController < ApplicationController
...
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
@user.roles.build
flash[:success] = "Profile updated"
redirect_to @user
else
@title = "Edit" + " " + @user.username
render 'edit'
end
end
...
end
and in the 'edit' view page I intend to have checkboxes to update the User record with an associated role:
EDIT: Changed the "check_box" with "check_box_tag" ... the check boxes appear properly, but the values are not saved.
<%= form_for(@user) do |f| %>
...
<div class="field">
<%= f.label :roles %><br />
<%= f.fields_for :role_ids do |r| %>
<% @roles.each do |role| %>
<%= check_box_tag "user[roles][]", role.id, @user.roles.include?(role.id) %>
<%= role.name %>
<% end %>
<%= hidden_field_tag "user[roles][]", "" %>
<% end %>
</div>
<% end %>
With this code I even get an error where 'Roles' have no association.
EDIT: this was corrected with the accepts_nested_attributes_for :role
. Thanks!
No association found for name `roles'. Has it been defined yet?
I am really confused where I am doing something wrong. Your help would be much appreciated.
Aurelien
Upvotes: 0
Views: 1905
Reputation: 909
Finally solved the problems and thought I could share.
The models associations but I did change the attr_accessible:
class User < ActiveRecord::Base
has_many :assignments, :dependent => :destroy
has_many :roles, :through => :assignments, :foreign_key => :role_id
accepts_nested_attributes_for :roles
attr_accessor :password
attr_accessible ..., :roles_ids
...
end
In the User controller for the edit and update action.
def edit
@title = "Edit" + " " + @user.username
@roles = Role.find(:all)
@user.assignments.build
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:success] = "Profile updated"
redirect_to @user
else
@title = "Edit" + " " + @user.username
render 'edit'
end
end
The important part was the view part and assigning the right names for the checkbox tags
<%= form_for(@user) do |f| %>
<div class="field">
<%= f.label :roles %><br />
<%= f.fields_for :role_ids do |r| %>
<% @roles.each do |role| %>
<%= check_box_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<%= role.name %>
<% end %>
<%= hidden_field_tag "user[role_ids][]", @user.id %>
<% end %>
</div>
The check_box_tag
lets the form save an array and gives more control than check_box
Then in order to assign the multiple Role ids, the name of the check_box_tag should include user[roles_ids][]
.
Finally the last parameter of the check_box_tag returns if the User has already the roles and checks the checkboxes if true.
I must admit that the name part of the check_box_tags is really confusing but it works :).
Upvotes: 0
Reputation: 25767
You have to use the same name with "accepts_nested_attributes_for" as you used defining the association:
class Assignment < ActiveRecord::Base
belongs_to :user
belongs_to :role
accepts_nested_attributes_for :role
end
Upvotes: 2