如何在Rails中组织复杂的回调? [英] How to organize complex callbacks in 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 :: Basehas_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屋!