why can't I save to a join table in a migration or rake task?

where is member_role coming from?

also, the save! is not necessary, as the << method saves the data in the join table.

Hi Chris,

Here's is the rake task version. member_role is a local variable with the value of a Role object with the title "member".

  desc "setup_roles for users."   task :setup_roles => :environment do     anonymous_role = Role.find_or_create_by_title('anonymous')     member_role = Role.find_or_create_by_title('member')     mananger_role = Role.find_or_create_by_title('manager')     author_role = Role.find_or_create_by_title('author')     admin_role = Role.find_or_create_by_title('admin')     User.find(:all).each {|u| u.roles << member_role; u.save! }     anonymous = User.find_by_login('Anonymous')     anonymous.roles.each {|r| r.destroy }     anonymous.roles << anonymous_role     stephen = User.find_by_login('stephen')     stephen.roles << admin_role   end

I added the save! just to see if saving the object to which the collection is related would make a difference. It didn't and I should have deleted it from my example before posting the question.

After running the migration listed below and then running the rake task listed above I have just two entries in the table roles_users, one for the anonymous user and one for me. If instead I run these two commands in script/console:

member_role = Role.find_or_create_by_title('member') User.find(:all).each {|u| u.roles << member_role }

The new entries are created in the roles_users joint table for all the users.

Here's the migration I keep running up and down:

class AddRolesUsers < ActiveRecord::Migration   def self.up     create_table "#{RAILS_APPLICATION_PREFIX}roles_users", :id => false, :force => true do |t|       t.column "role_id", :integer       t.column "user_id", :integer     end
  end

  def self.down     drop_table "#{RAILS_APPLICATION_PREFIX}roles_users"     Role.delete_all   end end

try this

replace

User.find(:all).each {|u| u.roles << member_role }

with

User.find(:all).each do |u|   p "#{u.roles.size}"   u.roles << member_role   p "#{u.roles.size}"   p "added member role to #{u.name}" end

and see what happens

try this

replace

User.find(:all).each {|u| u.roles << member_role }

with

User.find(:all).each do |u| p "#{u.roles.size}" u.roles << member_role p "#{u.roles.size}" p "added member role to #{u.name}" end

and see what happens

Chris,

Thanks so much for providing another set of eyes. I took your suggestion and expanded on it. Quickly here was the problem:

  anonymous.roles.each {|r| r.destroy }

What that actually does is delete all the roles_users associations that point to the any roles the anonymous user has:

This is the command that does what I intended:

  anonymous.roles.delete_all

For anybody else that finds this email in the future here's what I put in the rake task to help me debug the problem:

  task :setup_roles => :environment do     anonymous_role = Role.find_or_create_by_title('anonymous')     member_role = Role.find_or_create_by_title('member')     mananger_role = Role.find_or_create_by_title('manager')     author_role = Role.find_or_create_by_title('author')     admin_role = Role.find_or_create_by_title('admin')     User.find(:all).each do |u|       puts "\n--#{u.name}--"       puts " roles: size: #{u.roles.size}"       u.roles << member_role       puts " added member role to #{u.name}: u.roles << member_role"       puts " roles: size: :#{u.roles.size}"     end     puts "\n1: Checking Users for Roles:"     User.find(:all).each do |u|       puts "\n--#{u.name}--"       puts " roles: size: #{u.roles.size}"     end     anonymous = User.find_by_login('Anonymous')     anonymous.roles.each {|r| r.destroy } # *** this is the problem ***     anonymous.roles << anonymous_role     stephen = User.find_by_login('stephen')     stephen.roles << admin_role     puts "\n2: Checking Users for Roles:"     User.find(:all).each do |u|       puts "\n--#{u.name}--"       puts " roles: size: #{u.roles.size}"     end   end

On the first loop I got output like this:

--Anonymous User--   roles: size: 0   added member role to Anonymous User: u.roles << member_role   roles: size: :1

--Stephen Bannasch--   roles: size: 0   added member role to Stephen Bannasch: u.roles << member_role   roles: size: :1

--Carolyn Staudt--   roles: size: 0   added member role to Carolyn Staudt: u.roles << member_role   roles: size: :1

...

Everything still looks fine right after that:

1: Checking Users for Roles:

--Anonymous User--   roles: size: 1

--Stephen Bannasch--   roles: size: 1

--Carolyn Staudt--   roles: size: 1

...

But at the end it looks like this:

2: Checking Users for Roles:

--Anonymous User--   roles: size: 1

--Stephen Bannasch--   roles: size: 1

--Carolyn Staudt--   roles: size: 0

...

All the roles_users associations I made for the Users are gone.