Rails检查HABTM关联是否已更改

时间:2017-07-04 10:55:08

标签: ruby-on-rails ruby activerecord callback

我有角色表

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

和另一个表user_roles

guest

我正在尝试在更新用户角色时执行某些操作,说明从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

.changed?

但它没有按预期工作(role正在检查print_role_updated表中的值是否已更新?)。

如果用户角色更新为不同的角色,如何运行role_updated?方法?

修改

我尝试过Doctor的答案,但即使记录正在更新,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 也会返回false

sentence = 'I helped Adidas brand rebuild their design system'
words  = ["Adidas", "brand"]

sentence = sentence.split(/\W+/)
sentence.map! do |word|
  words.include?(word) ? "<span class='highlight'>#{word}</span>" : "<span>#{word}</span>"
end


puts sentence 
# => 
<span>I</span>
<span>helped</span>
<span class='highlight'>Adidas</span>
<span class='highlight'>brand</span>
<span>rebuild</span>
<span>their</span>
<span>design</span>
<span>system</span>

3 个答案:

答案 0 :(得分:2)

在模型中尝试以下代码:

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

答案 1 :(得分:1)

我认为_changed?仅适用于属性而非类。 由于您有多对多关联,因此无法检查一个对象。 我会尝试朝这个方向努力:

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

如果用户只有一个角色(很遗憾,您的代码中不清楚)那么以下内容应该有效,或者不是吗?

if user_roles.changed?

更新,因为您指定用户可以拥有多个角色。应该考虑一些修正:

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

更新2: 事实证明,changed?在新创建的对象上是假的,因此我之前的更新无效。

尝试将changed?更改为以下内容:

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

老实说这是我在这里做的一个猜测,但你可以试试吗?我很想看看是否有效

答案 2 :(得分:1)

我找到了解决方案。问题在于,一旦设置了新值,就会在数据库中更新HABTM关系

这是您的示例的变通方法,以实现HABTM更改的方法。可能不适用于您的确切情况,但知道这一点您就会明白

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