Summary
--------------------------------------------------------------------
I feel that it should be possible to set a collection directly to an 
array and have those changes propagated to the database. It should 
perform a two-way diff between the old array and the new, adding and 
removing records from the n-n table as appropriate.
Details
--------------------------------------------------------------------
I have an ACL-type setup with tables ''users'',
''roles'', and
''users_roles''; the models for each setup the habtm
relationship between
them:
   class User < ActiveRecord::Base
     has_and_belongs_to_many :roles
     #...
   end
   class Role < ActiveRecord::Base
	 has_and_belongs_to_many :users
	 #...
   end
At runtime, this sets up a users= setter method for a Role:
   irb(main):025:0> sa = Role.find 6
   => #<Role:0x2474f34
@attributes={"name"=>"Super-Admin",
   "id"=>"6"}>
   irb(main):026:0> sa.methods.select{|n|n=~/user/}.sort
   => ["add_users", "has_users?",
"remove_users", "users", "users=",
   "users_count"]
Using the #<<, and #remove_users methods (and #clear) do work as 
desired:
   irb(main):032:0> sa.users << User.find_all
   => [#<User:0x245d154 @errors=#<ActiveRecord::Errors:0x245c90c
   @errors={}, @base=#<User:0x245d154 ...>>,
   @attributes={"zip"=>"80303",
"nickname"=>"Phrogz",
   "disabled_flag"=>"f",
"lastname"=>"Kistner",
"firstname"=>"Gavin",
   "id"=>"1", "phone"=>nil,
"password"=>"foo",
"login"=>"phrogz",
  
"email"=>"gavin-XtLdkLkwz3ZWk0Htik3J/w@public.gmane.org"},
@new_record_before_save=nil>]
   irb(main):033:0> sa = Role.find 6
   => #<Role:0x2450f94
@attributes={"name"=>"Super-Admin",
"id"=>"6"}>
   irb(main):034:0> sa.users
   => [#<User:0x244e7f8
@attributes={"zip"=>"80303",
"nickname"=>"Phrogz",
   "role_id"=>"6",
"disabled_flag"=>"f",
"lastname"=>"Kistner",
   "firstname"=>"Gavin",
"id"=>"1", "phone"=>nil,
"user_id"=>"1",
   "password"=>"foo",
"login"=>"phrogz",
"email"=>"gavin-XtLdkLkwz3ZWk0Htik3J/w@public.gmane.org"}>]
I expect to be able to set this collection directly, but this does not 
work. For example:
   irb(main):027:0> sa.users
   => []
   irb(main):028:0> sa.users = User.find_all
   => [#<User:0x246bc18
@attributes={"zip"=>"80303",
"nickname"=>"Phrogz",
   "disabled_flag"=>"f",
"lastname"=>"Kistner",
"firstname"=>"Gavin",
   "id"=>"1", "phone"=>nil,
"password"=>"foo",
"login"=>"phrogz",
  
"email"=>"gavin-XtLdkLkwz3ZWk0Htik3J/w@public.gmane.org"}>]
   irb(main):029:0> sa.save => true
   irb(main):030:0> sa = Role.find 6
   => #<Role:0x2462528
@attributes={"name"=>"Super-Admin",
"id"=>"6"}>
   irb(main):031:0> sa.users
   => []
I can understand why this feature might not have been implemented,
but given the presence of a #users= method, I expected to be able to
set it to an array. This should be possible given an implementation
of the following code (albeit in the generic case for any habtm):
class Role
   def users=( new_array )
	 self.users << ( new_array - self.users )
	 self.remove_users( self.users - new_array )
   end
end
--
(-, /\ \/ / /\/