Paperclip 图像尺寸自定义验证器

7
这是我的Image模型,其中我实现了一种验证附件尺寸的方法:
class Image < ActiveRecord::Base
  attr_accessible :file

  belongs_to :imageable, polymorphic: true

  has_attached_file :file,
                     styles: { thumb: '220x175#', thumb_big: '460x311#' }

  validates_attachment :file,
                        presence: true,
                        size: { in: 0..600.kilobytes },
                        content_type: { content_type: 'image/jpeg' }

  validate :file_dimensions

  private

  def file_dimensions(width = 680, height = 540)
    dimensions = Paperclip::Geometry.from_file(file.queued_for_write[:original].path)
    unless dimensions.width == width && dimensions.height == height
      errors.add :file, "Width must be #{width}px and height must be #{height}px"
    end
  end
end

这段代码可以正常工作,但由于方法中的宽度和高度取了固定值,所以无法重复使用。我希望将其转化为自定义验证器,以便在其他模型中也可以使用。我已经阅读了相关指南,知道在 app/models/dimensions_validator.rb 中应该是这样的:

class DimensionsValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    dimensions = Paperclip::Geometry.from_file(record.queued_for_write[:original].path)

    unless dimensions.width == 680 && dimensions.height == 540
      record.errors[attribute] << "Width must be #{width}px and height must be #{height}px"
    end
  end
end

但我知道我错过了什么,因为这段代码不起作用。问题是我想在我的模型中像这样调用验证器:validates :attachment, dimensions: { width: 300, height: 200}。你有什么关于如何实现此验证器的想法吗?

1
我不确定,但我认为您可以通过选项属性访问宽度和高度..例如:options[:width]options[:height] - Tim Baas
2个回答

19

将此代码放入 app/validators/dimensions_validator.rb 文件中:

class DimensionsValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    # I'm not sure about this:
    dimensions = Paperclip::Geometry.from_file(value.queued_for_write[:original].path)
    # But this is what you need to know:
    width = options[:width]
    height = options[:height] 

    record.errors[attribute] << "Width must be #{width}px" unless dimensions.width == width
    record.errors[attribute] << "Height must be #{height}px" unless dimensions.height == height
  end
end

然后,在模型中:

validates :file, :dimensions => { :width => 300, :height => 300 }

只要您将文件放置在models/目录下并按照Rails约定进行命名(dimensions_validator.rb),就不必将验证器添加到load_path中。我已经编辑了答案。谢谢! - Agis
太好了。如果只有上传了图像,我们该如何执行检查?我尝试过一些方法,例如 `unless record.nil?' 和 'unless value.nil?',但都没有成功。 - Agis
你可以尝试使用 if value.present?,但我认为 value.nil? 应该也能起作用。当 value 没有被上传并且你进行调试时,它的值是多少? - Tim Baas
3
我建议不要把这个文件放到/app/models目录下。把文件放在/app/validators目录下仍然会使Rails自动加载文件,并且保持你的模型目录干净整洁,符合单一职责原则。 - Nathan
为什么不将其添加为gem?我会创建一个。 - svelandiag

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接