The ROR Wiki has a pretty complete solution that might do what you want
http://wiki.rubyonrails.org/rails/pages/CheckboxHABTM
The crux of the matter involves creating a sub-hash of preference_ids
that
is then used to find the preferences and map them to the user. Then
user.save saves the user and all the dependent preference data. It does
involve one oddity - you have to use the older style check_box_tag
helper -
even if the rest of your form is written using form_for syntax. I did
some
searching and experimenting and could not find any way to use the
check_box
helper and constrict the list I would need for mapping.
I followed the directions on the wiki page - and snagged some code from
an
older version of ActiveRBAC - and my first attempt worked. However, I am
trying to add another, practically identical set of checkboxes but the
mapping isn’t working. Or to be more specific, the log shows that the
original mappings are deleted, the new mappings are created, AND THEN
THE
MAPPINGS ARE DELETED AGAIN!? I cannot for the life of me figure out
where
that extra delete is coming from. I tried removing the roles stuff from
the
view and controller, but that didn’t make the event mapping work.
development.log
Processing UserController#update (for 131.215.130.72 at 2007-07-27
14:34:59)
[POST]
Session ID: 663471e0ab9cbe10e33b4ce5d4bbffd6
Parameters: {“user”=>{“event_ids”=>[“1”, “6”], “role_ids”=>[“1”, “2”],
“first_name”=>“C”, “last_name”=>“K”, “email”=>“[email protected]”},
“commit”=>“Update”, “action”=>“update”, “id”=>“2”,
“controller”=>“admin/user”}
^[[4;35;1mUser Columns (0.002214)^[[0m ^[[0mSHOW FIELDS FROM
users^[[0m
^[[4;36;1mUser Load (0.000595)^[[0m ^[[0;1mSELECT * FROM users WHERE
(users.id
= 2) LIMIT 1^[[0m
^[[4;35;1mRole Columns (0.001494)^[[0m ^[[0mSHOW FIELDS FROM
roles^[[0m
^[[4;36;1mRole Load (0.000513)^[[0m ^[[0;1mSELECT * FROM roles WHERE
(roles.rolename
= ‘Admin’) LIMIT 1
^[[0m
^[[4;35;1mJoin Table Columns (0.001440)^[[0m ^[[0mSHOW FIELDS FROM
roles_users^[[0m
^[[4;36;1mRole Load (0.000601)^[[0m ^[[0;1mSELECT * FROM roles INNER
JOIN roles_users ON roles.id = roles
_users.role_id WHERE (roles_users.user_id = 2 ) ^[[0m
^[[4;35;1mUser Load (0.000620)^[[0m ^[[0mSELECT * FROM users WHERE
(users.id
= 2) ^[[0m
^[[4;36;1mJoin Table Columns (0.001443)^[[0m ^[[0;1mSHOW FIELDS FROM
events_users^[[0m
^[[4;35;1mEvent Load (0.000583)^[[0m ^[[0mSELECT * FROM events INNER
JOIN events_users ON events.id = eve
nts_users.event_id WHERE (events_users.user_id = 2 ) ^[[0m
^[[4;36;1mSQL (0.000158)^[[0m ^[[0;1mBEGIN^[[0m
^[[4;35;1mSQL (0.000139)^[[0m ^[[0mCOMMIT^[[0m
CNK after collecting all the role and event info but before
update_attributes
^[[4;36;1mEvent Columns (0.001768)^[[0m ^[[0;1mSHOW FIELDS FROM
events^[[0m
^[[4;35;1mEvent Load (0.000623)^[[0m ^[[0mSELECT * FROM events WHERE
(events.id
IN (1,6)) ^[[0m
^[[4;36;1mSQL (0.000163)^[[0m ^[[0;1mBEGIN^[[0m
^[[4;35;1mevents_users Columns (0.001388)^[[0m ^[[0mSHOW FIELDS FROM
events_users^[[0m
^[[4;36;1mSQL (0.000391)^[[0m ^[[0;1mINSERT INTO events_users
(event_id
, user_id
) VALUES (1, 2)^[[0m
^[[4;35;1mevents_users Columns (0.001350)^[[0m ^[[0mSHOW FIELDS FROM
events_users^[[0m
^[[4;36;1mSQL (0.000362)^[[0m ^[[0;1mINSERT INTO events_users
(event_id
, user_id
) VALUES (6, 2)^[[0m
^[[4;35;1mSQL (0.004550)^[[0m ^[[0mCOMMIT^[[0m
^[[4;36;1mRole Load (0.000557)^[[0m ^[[0;1mSELECT * FROM roles WHERE
(roles.id
IN (1,2)) ^[[0m
^[[4;35;1mJoin Table Columns (0.001406)^[[0m ^[[0mSHOW FIELDS FROM
roles_users^[[0m
^[[4;36;1mRole Load (0.000636)^[[0m ^[[0;1mSELECT * FROM roles INNER
JOIN roles_users ON roles.id = roles
_users.role_id WHERE (roles_users.user_id = 2 ) ^[[0m
^[[4;35;1mSQL (0.000164)^[[0m ^[[0mBEGIN^[[0m
^[[4;36;1mSQL (0.000153)^[[0m ^[[0;1mCOMMIT^[[0m
^[[4;35;1mSQL (0.000138)^[[0m ^[[0mBEGIN^[[0m
^[[4;36;1mSQL (0.000444)^[[0m ^[[0;1mDELETE FROM events_users WHERE
user_id = 2 AND event_id IN (1,6)^[[0
m
^[[4;35;1mSQL (0.000612)^[[0m ^[[0mCOMMIT^[[0m
^[[4;36;1mSQL (0.000159)^[[0m ^[[0;1mBEGIN^[[0m
^[[4;35;1mUser Load (0.000810)^[[0m ^[[0mSELECT * FROM users WHERE
(LOWER(users.email) = '[email protected]
AND users.id <> 2) LIMIT 1^[[0m
^[[4;36;1mUser Update (0.000581)^[[0m ^[[0;1mUPDATE users SET
created_at
= ‘2007-07-10 16:25:56’, last_name
= 'K, first_name
=
'C,
email
= '[email protected], updated_at
= ‘2007-07-27 14:34:59’ WHERE
id
= 2^[[0m
^[[4;35;1mSQL (0.000540)^[[0m ^[[0mCOMMIT^[[0m
Redirected to http://
The models:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
has_and_belongs_to_many :events
…
end
class Event < ActiveRecord::Base
has_and_belongs_to_many :users
…
end
The view:
<% form_for :user do |f| %>
…
Roles
<% for role in Role.find(:all) %>
<%= check_box_tag "user[role_ids][]", "#{role.id}",
current_role?(role) %> <%= role.rolename %>
<% end %>
Events
<% for event in Event.find(:all, :conditions => "signup = true") %>
<%= check_box_tag "user[event_ids][]", "#{event.id}",
current_event?(event) %> <%= event.title %>
<% end %>
<%= submit_tag 'Update' %>
<% end %>
Helpers - to get the current roles/events checked:
module Admin::UserHelper
def current_role?(role)
if @user
@user.roles.include?(role)
else
false
end
end
def current_event?(event)
if @user
@user.events.include?(event)
else
false
end
end
end
And the controller:
class Admin::UserController < ApplicationController
require_dependency ‘user’
def update
@user = User.find(params[:id].to_i)
if request.post?
# get an array of roles and set the role associations
params[:user][:roles] = [] if params[:user][:roles].nil?
roles = params[:user][:roles].collect { |i| Role.find(i) }
@user.roles = roles
# get an array of events and set the event associations
params[:user][:events] = [] if params[:user][:events].nil?
events = params[:user][:events].collect { |i| Event.find(i) }
@user.events = events
if @user.update_attributes(params[:user])
redirect_to :action => "show", :id => @user.id
end
end
end
end