简体   繁体   English

Rails检查HABTM关联是否已更改

[英]Rails check if HABTM association is changed

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 和另一个表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 当用户的角色更新时,我试图做一些操作,从guestauthor

#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 ?). 但它没有按预期工作( .changed?正在检查role表中的值是否更新?)。

How do I run print_role_updated method whenever user roles get updated to a diffrent one? 每当用户角色更新为不同的角色时,如何运行print_role_updated方法?

edit 编辑

I tried Doctor's answer but role_updated? 我试过医生的答案,但是role_updated? is returning false even though the record is being updated 即使正在更新记录,也会返回false

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

try below code in model: 尝试下面的模型代码:

user.rb user.rb

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

  private

  def print_role_updated
    puts "User role changed"
  end

  def user_roles_changed?
    u = User.find(self.id)
    u.role != self.role # it check existing role and role saved in db 
  end
end

I think the _changed? 我觉得_changed? does only work for attributes not classes. 仅适用于属性而非类。 And since you have a many to many association you can't check on one object. 由于您有多对多关联,因此无法检查一个对象。 I would try something in this direction: 我会尝试朝这个方向努力:

if user_roles.any? {|a| a.changed?} 

if a user only has a single role (sorry it is not clear from your code) then the following should work, or doesn't it ? 如果用户只有一个角色(很遗憾,您的代码中不清楚)那么以下内容应该有效,或者不是吗?

if user_roles.changed?

Update since you specified that a user can have many roles. 自您指定用户可以拥有许多角色以来的更新。 There should be a few corrections you should consider: 你应该考虑一些修正:

class Use < ActiveRecord::Base
  has_many :user_roles
  after_update :print_role_updated if: user_roles.any? {|a| a.changed?} 
  .
  .


  private

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

Update 2: As it turns out, changed? 更新2:事实证明, changed? is false on newly created objects, so my previous update is not working. 在新创建的对象上为false,因此我之前的更新无效。

Try to change the changed? 尝试更改已changed? to the following: 以下内容:

user_roles.any? { |a| a.new_record? || a.marked_for_destruction? || a.changed? }

To be honest it is a bit a guessing I do here, but can you please try it? 说实话,我在这里做了一个猜测,但你可以试试吗? I would love to see if that works 我很想知道这是否有效

I found a solution. 我找到了解决方案。 the problem is that the HABTM relationship is updated in the db as soon as the new values are set 问题是,一旦设置了新值,就会在db中更新HABTM关系

here is my workaround for your example to implement an HABTM changed method. 这是我为您的示例实现HABTM更改方法的解决方法。 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM