[英]Ruby on Rails — Stack level too deep
model: 模型:
after_save :set_correct_post_type
def set_correct_post_type
if self.document.present?
if (find_mime_type(self.document.original_filename) == "application/vnd.openxmlformats-officedocument.presentationml.presentation") || (find_mime_type(self.document.original_filename) == "application/vnd.ms-powerpoint")
self.update_attributes(:post_type => 3)
elsif (find_mime_type(self.document.original_filename) == "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ) || (find_mime_type(self.document.original_filename) == "application/msword") || (find_mime_type(self.document.original_filename) == "application/pdf")
self.update_attributes(:post_type => 2)
elsif (MIME::Types.type_for(self.document.original_filename).first.content_type == "image/png") || (MIME::Types.type_for(self.document.original_filename).first.content_type =="image/jpeg") || (MIME::Types.type_for(self.document.original_filename).first.content_type == "image/jpg")
self.update_attributes(:post_type => 5)
end
end #line17
end
Logs: 日志:
(0.3ms) rollback transaction
Completed 500 Internal Server Error in 1939ms (ActiveRecord: 37.5ms)
SystemStackError (stack level too deep):
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
app/models/teacher_post.rb:17:in `set_correct_post_type'
And then it repeats the last line again and again until I stop it manually. 然后它一次又一次地重复最后一行,直到我手动停止它为止。 Can anyone tell me what I'm doing wrong? 谁能告诉我我在做什么错?
The reason for "stack level too deep error" is because you are calling update_attributes
inside after_save
callback, which will invoke the callback after_save
again, calling update_attributes
again, and so on... 之所以“堆栈级别太深错误”是因为你调用update_attributes
里面after_save
回调,这将调用回调after_save
再次呼唤update_attributes
再次,等等...
Change it to following: 将其更改为以下内容:
before_save :set_correct_post_type
def set_correct_post_type
if self.document.present?
if (find_mime_type(self.document.original_filename) == "application/vnd.openxmlformats-officedocument.presentationml.presentation") || (find_mime_type(self.document.original_filename) == "application/vnd.ms-powerpoint")
self.post_type = 3
elsif (find_mime_type(self.document.original_filename) == "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ) || (find_mime_type(self.document.original_filename) == "application/msword") || (find_mime_type(self.document.original_filename) == "application/pdf")
self.post_type = 2
elsif (MIME::Types.type_for(self.document.original_filename).first.content_type == "image/png") || (MIME::Types.type_for(self.document.original_filename).first.content_type =="image/jpeg") || (MIME::Types.type_for(self.document.original_filename).first.content_type == "image/jpg")
self.post_type = 5
end
end
end
When you call update_attributes, the callbacks are called, as your method set_correct_post_type is set as "after_save", you end with an loop. 当您调用update_attributes时,将调用回调,因为您的方法set_correct_post_type设置为“ after_save”,因此以循环结尾。
You call save on you method that triggers the set_correct_post_type method that call update_attributes that triggers the set_correct_post_type method that call update_attributes... 您调用保存方法,该方法将触发调用update_attributes的set_correct_post_type方法,该方法将触发调用update_attributes的set_correct_post_type方法。
If you don't want to trigger the callbacks in your method, look at update_columns instead of update_attributes. 如果您不想在方法中触发回调,请查看update_columns而不是update_attributes。 Of consider setting attribute with a before_save instead of a after save. 考虑使用before_save而不是after保存来设置属性。
If you have your custom code, without any gems etc, avoid using rails callbacks. 如果您有自定义代码,没有任何gem等,请避免使用rails回调。 I'd recommend use Serice Object ex. 我建议使用Serice Object ex。 CreateTeacherPost
which will create a post, do magic with params, types etc all in one Transaction. CreateTeacherPost
可以创建一个帖子,在一个事务中使用参数,类型等进行魔术处理。 This way you will avoid problems like below and you will always know whats going on without callbacks magic. 这样,您将避免出现以下问题,并且您将始终知道发生了什么,而没有回调魔术。
But if you really want to use this pattern it's going into an infinite loop because each update_attributes is calling after_save! 但是,如果您真的想使用此模式,则会进入无限循环,因为每个update_attributes都调用after_save! callback method. 回调方法。 You could use update_column
method or before_save
callback and set attribute directly using self.post_type=number
. 您可以使用update_column
方法或before_save
回调并直接使用self.post_type=number
设置属性。 But first will call SQL update the second time, there is no reason to do this. 但是首先是第二次调用SQL update,所以没有理由这样做。
One more :) if you have to/want to use after callback better use after_commit callback. 还有一个:)如果您必须/想要在回调后使用,最好使用after_commit回调。 It's much safer. 更安全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.