On Apr 26, 2005, at 1:54 PM, Edgardo Hames wrote: > In case this solution is way too far from being done, how can I handle > checking and unchecking the different authors in that table on the > Controller side? What I would need to do is remove the unchecked > authors and add the checked ones. [...] How do you all usually solve > this problem? The functionality of checkboxes is the same as that of a multiple-select field, though the UI is different. I have two tables in a habtm relationship; following is the (hacked-together) code that I've used (which happens to use selects, but which would be easy to modify for checkboxes). The short answer is: When you are saving, get a list of all the items currently stored for the relationship into an array, get the list of all the new items desired into a new array, and then do a two-way difference to figure out which relationships must be removed and which must be added. Here's the relevant parts of my code: # POSTGRESQL SCHEMA create table roles ( id serial primary key, name varchar(100) not null ); create table acts ( id serial primary key, action_path varchar(100) not null ); create table acts_roles ( act_id integer references acts on delete cascade, role_id integer references roles on delete cascade, primary key ( act_id, role_id ) ); #FILE app/model/act.rb class Act < ActiveRecord::Base has_and_belongs_to_many :roles end #FILE app/model/role.rb class Role < ActiveRecord::Base has_and_belongs_to_many :acts has_and_belongs_to_many :users #This really should be done for all habtm, IMO def users=( new_array ) self.remove_users( self.users - new_array ) self.users << ( new_array - self.users ) self.users end #This really should be done for all habtm, IMO def acts=( new_array ) self.remove_acts( self.acts - new_array ) self.acts << ( new_array - self.acts ) self.acts end end #FILE app/controllers/role.rb class RoleController < ApplicationController def edit @role = Role.find_by_id @params[ :id ] @page_title = "Edit Role '#{@role.name}'" @all_actions = Act.find_all.sort_by{ |act| act.action_path } @actions_allowed = @role.acts end def update role = Role.find( role_atts["id"] ) role.acts = @params['role']['acts'].collect{ |id| Act.find id } role.save end end #FILE app/views/role/edit.rhtml <!-- snip --> <fieldset id="actions" class="two_column"> <legend><strong>Actions</strong> permitted by <%=@role.name%></legend> <select name="role[acts][]" multiple="multiple" size="<%=select_length%>"> <%=options_from_collection @all_actions, @role.acts, :action_path %> </select> </fieldset> #FILE app/helpers/application.rb module ApplicationHelper # Creates a list of HTML option tags based on a collection of model instances # with the ability to provide a second collection of elements which should be selected def options_from_collection( all_items, selected, text_method=:name, value_method=:id ) use_include = selected.respond_to?( :include? ) && !selected.is_a?( String ) all_items.inject([]) do |options, element| val = element.send( value_method ) text = element.send( text_method ) is_selected = use_include ? selected.include?( element ) : val == selected if is_selected options << "<option value=\"#{html_escape(val.to_s)}\" selected=\"selected\">#{html_escape(text.to_s)}</option>" else options << "<option value=\"#{html_escape(val.to_s)}\">#{html_escape(text.to_s)}</option>" end end.join( "\n" ) end end