Rails check if HABTM association is changed

Viewed 2116

I have a roles table

select * from roles;

 id |   name
----+----------
  1 | admin
  2 | user
  3 | author
  4 | guest
  5 | manager

and another table user_roles

select * from user_roles;

 role_id | user_id
---------+---------
       3 |       1
       3 |       2
       3 |       3
       4 |       5
       3 |       6
       5 |       7
       5 |       8
       1 |       9
       1 |      11



#role.rb

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users, join_table: 'user_roles', class_name: user_class.to_s
end

I am trying to do some actions when a user's role is updated say, from guest to author

#user.rb

class Use < ActiveRecord::Base
  after_update :print_role_updated if: :user_roles_changed?
  .
  .

  private

  def user_roles_changed?
    user_roles.any? { |role| role.changed? }
  end

  def print_role_updated
    puts "User role changed from #{old_role} to #{new_role}"
  end
end

But it is not working as expected (.changed? is checking whether the value in role table is updated ?).

How do I run print_role_updated method whenever user roles get updated to a diffrent one?

edit

I tried Doctor's answer but role_updated? is returning false even though the record is being updated

class Use < ActiveRecord::Base
  has_many :user_roles
  after_update :print_role_updated if: role_updated?
  .
  .


  private

  def role_updated?
    user_roles.any? {|a| a.changed?} 
  end

  def print_role_updated
    puts "User role changed from #{old_role} to #{new_role}"
  end
end
3 Answers

I found a solution. the problem is that the HABTM relationship is updated in the db as soon as the new values are set

here is my workaround for your example to implement an HABTM changed method. may not work for your exact case but knowing this you'll get the idea

class User < ActiveRecord::Base

  ...
  def user_role_ids=(ids)
    @user_roles_changed = ids != user_role_ids
    super(ids)
  end

  def user_roles_changed?
    !!@user_roles_changed
  end
end
Related