0

模型:

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

日志:

  (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'

然后它一次又一次地重复最后一行,直到我手动停止它。谁能告诉我我做错了什么?

4

3 回答 3

1

“堆栈级别太深错误”的原因是因为您在回调update_attributes内部after_save调用,它将再次调用回调after_save,再次调用update_attributes,等等......

将其更改为以下内容:

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
于 2018-07-02T10:25:12.037 回答
0

如果您有自定义代码,没有任何 gem 等,请避免使用 rails 回调。我建议使用 Serice Object ex。CreateTeacherPost这将创建一个帖子,在一个事务中使用参数、类型等进行魔术。这样你就可以避免像下面这样的问题,并且在没有回调魔法的情况下你将永远知道发生了什么。

但是如果你真的想使用这种模式,它就会进入一个无限循环,因为每个 update_attributes 都在调用 after_save!回调方法。您可以使用update_column方法或before_save回调并直接使用设置属性self.post_type=number。但是第一次会调用 SQL 更新第二次,没有理由这样做。

还有一个:) 如果您必须/想要使用 after 回调,最好使用 after_commit 回调。它更安全。

于 2018-07-02T14:26:59.520 回答
0

当您调用 update_attributes 时,将调用回调,因为您的方法 set_correct_post_type 设置为“after_save”,您以循环结束。

你调用 save 方法触发 set_correct_post_type 方法调用 update_attributes 触发 set_correct_post_type 方法调用 update_attributes ...

如果您不想在方法中触发回调,请查看 update_columns 而不是 update_attributes。考虑使用 before_save 而不是 after save 设置属性。

于 2018-07-02T10:27:00.293 回答