【发布时间】:2013-12-29 00:25:30
【问题描述】:
我有这个模型的图片附加到另一个模型(Work):
class WorkPicture < ActiveRecord::Base
after_initialize :default_values
after_update :reprocess_picture, if: :cropping_changed?
belongs_to :work, inverse_of: :pictures
has_attached_file :picture, styles: lambda { |attachment| { big: { geometry: "1500x>", format: :png },
thumb: attachment.instance.thumb_options } },
url: "/pictures/:hash.:extension",
hash_secret: ENV["PAPERCLIP_SECRET_KEY"]
validates_attachment :picture, presence: true,
content_type: { content_type: /image/ }
scope :illustrative, -> { where(is_cover: false) }
# Default values
def default_values
self.is_cover = false if self.is_cover.nil?
self.crop_x = 0 if self.crop_x.nil?
self.crop_y = 0 if self.crop_y.nil?
end
def thumb_options
return { geometry: "", format: :png, convert_options: "-crop 360x222+#{crop_x.to_i}+#{crop_y.to_i}" }
end
private
def cropping_changed?
self.crop_x_changed? || self.crop_y_changed?
end
def reprocess_picture
picture.reprocess!
end
end
这些图片有双重用途:如果将is_cover 设置为false,它们将显示在相关作品的图库页面中。如果 is_cover 设置为 true,它们将被裁剪并用作列出所有作品的页面中相关作品的“图标”。
在工作编辑页面上,您可以更改裁剪的 x 和 y 坐标。这意味着一旦新坐标进入,图像应该被重新处理,以便显示正确的区域。
为此,我在模型上设置了两个属性crop_x 和crop_y,它们存储了裁剪窗口的位置。通过after_update,我首先检查这些坐标是否已更改,如果是,我告诉Paperclip 重新处理图像以正确裁剪。
运行此代码时,执行进入无限循环。我想我已经确定了造成这种情况的原因:after_updatedoesn't clearActiveRecord::Dirty 属性(例如self.crop_x_changed?)使其对开发人员更有用,但是当我在 Paperclip 本身制作的图片上调用reprocess! 时更改我的模型并调用save,这反过来又会导致再次触发after_update 回调。由于self.crop_x_changed? 和self.crop_y_changed? 从该链的开头仍然是true(这是因为它们似乎只有在after_update 运行后才被清除),这导致我的代码再次调用reprocess!,这继续这个无限循环。
我已经尝试了许多类似的代码变体,但似乎都无休止地循环或失败。有没有办法让我的代码正确执行这个功能?
【问题讨论】:
标签: ruby-on-rails ruby callback paperclip infinite-loop