如何在Rails中组织复杂的回调? [英] How to organize complex callbacks in Rails?

查看:159
本文介绍了如何在Rails中组织复杂的回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Rails应用程序,使用回调很多..所以我有很多函数调用:after_create和:after_commit在多个模型。





基本上我有以下情况:

  ActiveRecord :: Base 

has_many:children


after_create:first_function
after_commit:last_function

def first_function
if!self.processed?
self.children.create(:name =>Richard The Lion Heart)
self.processed = true
self.save!
end
end

def last_function
如果self.processed?
if!self.processing?
self.process
self.save!
self.processing = true
self.save!
end
end
end

end

所以你可以看到整个事情取决于一些奇怪的双布尔检查,因为否则second_function是每次模型被更新时被调用,它可以通过函数本身更新,因此函数被重复调用。



总的来说,这导致我必须为每个回调引发一个新的布尔检查。它工作,但我不认为它的优雅。我缺少什么?

解决方案

您应该能够重写该代码 - 类似这样的代码?当然,您的实际代码可能还有一些额外的复杂性 -

类Parent< ActiveRecord :: Base
has_many:children

#仅在创建新记录时调用
after_create:first_function

#仅为更新而调用新记录,应该仍然在当前事务内
after_update:last_function

private
def first_function
self.children.create(:name =>Richard狮子心)
#不在这里调用save,已经在事务中
end

def last_function
self.process
# t调用保存在这里,已经在事务中
end

def process
#do stuff ....
self.children [0] .update_attribute(: name,Beowulf)
end
end

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html


这是总共十二个回调,它为您在Active Record生命周期中为每个状态做出反应和准备提供了巨大的力量。对现有记录调用Base#save的顺序是类似的,除了每个_create回调被相应的_update回调代替。


使用

  p = Parent.new(:foo =>bar)
p.save
p.children [0] .name
#=> Richard The Lion Heart

p.update_attributes(:baz =>fud)
p.children [0] .name
#=> Beowulf

来自rails console的ActiveRecord回呼(使用awesome_print ap)

 > ap ActiveRecord :: Callbacks :: CALLBACKS 
[
[0]:after_initialize,
[1]:after_find,
[2]:after_touch,
[3] :before_validation,
[4]:after_validation,
[5]:before_save,
[6]:around_save, :before_create,
[11]:before_update,
[12]:around_update,
[10] :after_update,
[14]:before_destroy,
[15]:around_destroy,
[16]:after_destroy,
[ :after_rollback
]


I have a Rails application, that uses callbacks a lot.. so that I have quite a few functions getting called :after_create and :after_commit in multiple models.

I wonder if the way I am doing it right now is the best.

Basically I have the following scenario:

Class Parent < ActiveRecord::Base

has_many :children


after_create :first_function 
after_commit :last_function

    def first_function
        if !self.processed?
            self.children.create(:name => "Richard The Lion Heart")
            self.processed = true
            self.save!
        end
    end

    def last_function
        if self.processed?
            if !self.processing?
                self.process
                                    self.save!
                self.processing = true
                self.save!
            end
        end
    end

end

So you can see the whole thing depends on some strange dual boolean checks because otherwise second_function is getting called every time the model is being updated and it can be updated by the function itself and so the function is getting called repetitively.

Overall it leads me to the case where I have to introduce a new boolean check for every callback to fire off. It works but I don't see it as elegant. What am I missing?

解决方案

You should be able to rewrite that code -- something like this? Of course your real code probably has some additional complexity -- ALSO: this code is untested.

Class Parent < ActiveRecord::Base
  has_many :children

  # only called when a new record is created
  after_create :first_function 

  # only called for updates, not new records, should still be inside the current transaction
  after_update :last_function

  private
    def first_function
      self.children.create(:name => "Richard The Lion Heart")
      # don't call save in here, already in a transaction
    end

    def last_function
      self.process
      # don't call save in here, already in a transaction        
    end

    def process
      # doing stuff ....
      self.children[0].update_attribute(:name, "Beowulf")
    end
end    

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

That’s a total of twelve callbacks, which gives you immense power to react and prepare for each state in the Active Record life cycle. The sequence for calling Base#save for an existing record is similar, except that each _create callback is replaced by the corresponding _update callback.

usage

p = Parent.new(:foo => "bar")
p.save
p.children[0].name
# => "Richard The Lion Heart"

p.update_attributes(:baz => "fud")
p.children[0].name
# => Beowulf

ActiveRecord callbacks from rails console (with awesome_print ap)

> ap ActiveRecord::Callbacks::CALLBACKS
[
  [ 0] :after_initialize,
  [ 1] :after_find,
  [ 2] :after_touch,
  [ 3] :before_validation,
  [ 4] :after_validation,
  [ 5] :before_save,
  [ 6] :around_save,
  [ 7] :after_save,
  [ 8] :before_create,
  [ 9] :around_create,
  [10] :after_create,
  [11] :before_update,
  [12] :around_update,
  [13] :after_update,
  [14] :before_destroy,
  [15] :around_destroy,
  [16] :after_destroy,
  [17] :after_commit,
  [18] :after_rollback
]

这篇关于如何在Rails中组织复杂的回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆