【问题标题】:Get paperclip to crop the image without validating获取回形针以在不验证的情况下裁剪图像
【发布时间】:2026-01-23 05:05:02
【问题描述】:

大家好,* 成员。

我一直在关注这个guide,让用户拥有自己的头像。

但是我遇到了一个小问题。 当用户裁剪图像时,模型会尝试验证我的所有验证。 我的用户模型如下所示:

class User < ActiveRecord::Base

  has_attached_file :avatar, :styles => { :small => "100x100>", :large => "500x500>" }, :processors => [:cropper]

  attr_accessor :password, :crop_x, :crop_y, :crop_w, :crop_h
  attr_accessible :crop_x, :crop_y, :crop_w, :crop_h
  validates_confirmation_of :password
  validates_presence_of :password

当用户运行裁剪更新脚本时,user 模型会尝试验证密码。但是因为我在裁剪页面上没有密码字段,所以无法验证它。

这是作物的更新:

@user = User.find(current_user.id)
  if @user.update_attributes(params[:user])
    flash[:notice] = "Successfully updated user."
  end

我怎样才能以一种简单而干净的方式绕过这个?

【问题讨论】:

    标签: ruby-on-rails ruby validation paperclip


    【解决方案1】:

    调用#save 并传递false 以禁用对该数据库更新的验证。

    将您的控制器代码更改为:

    @user = User.find(current_user.id)
    @user.attributes = params[:user]
    if @user.save(false)
        flash[:notice] = "Successfully updated user."
    end
    

    如果您依赖 Paperclip 进行图像验证,这会给您带来麻烦。它可能会掩盖格式错误的图像文件的一些问题,但它可能值得权衡。

    【讨论】:

      【解决方案2】:

      尝试条件验证:

      validates_confirmation_of :password, :if => :password
      validates_presence_of :password, :if => :password
      

      【讨论】:

      • 我认为这不是一个好主意,这将导致原始表单中真正需要密码的问题
      • 并非如此。因为在这种情况下 if 会检查 null。密码为空的唯一方法是将其从表单中删除,或者在代码中将值设置为空。无论哪种方式,这都是编程而不是用户验证。我同意这是一个快速和肮脏的,但它是原始海报的深思熟虑。
      【解决方案3】:

      根据authlogic 使用的技术,仅在密码为新记录、密码已更改或加密密码(存储散列/加密密码的列)为空时尝试验证密码。

      class User
        validates_confirmation_of :password, :if => :require_password?
        validates_presence_of :password, :if => :require_password?
      
        def password=(pass)
          return if pass.blank?
      
          # Encrypt password, etc
          # ...
      
          @password_changed = true
        end
      
      
        private
          def require_password?
            new_record? || @password_changed || crypted_password.blank?
          end
      end
      

      【讨论】:

        【解决方案4】:

        与@htanata 类似的答案,但使用ActiveRecord:Dirty

        class User
          validates_confirmation_of :password, :if => 'self.password_changed?'
          validates_presence_of :password, :if => 'self.password_changed?'
        end
        

        【讨论】:

        • :if =&gt; :password_changed?为简洁起见。