逻辑大概是这样的,用户上传头像以后,然后就跳转到一个新的页面,然后在那个页面,利用 jcrop 插件,然后提交 crop_x crop_y crop_w crop_h 四个参数,以便后台进行裁剪。
在用户模型里是这样的:
class User
  include Mongoid::Document
  include Mongoid::Timestamps::Short
  # ...
  mount_uploader :avatar, AvatarUploader
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
  after_update :crop_avatar, if: :cropping?
  def cropping?
    !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
  end
  private
  def crop_avatar
    avatar.recreate_versions! if avatar.present?
  end
end
然后在 AvatarUploader 里大概是这样的:
class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  storage :file
  def store_dir
    # "uploads/#{model.class.to_s.underscore}/#{model.id}"
    "#{model.class.to_s.underscore}/#{mounted_as}"
  end
  def default_url
    _filename = ["default_avatar", version_name, "png"].join(".")
    # For Rails 3.1+ asset pipeline compatibility:
    return ActionController::Base.helpers.asset_path("fallback/#{_filename}")
    "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  end
  process :manual_crop
  version :thumb do
    process resize_to_fit: [50, 50]
  end
  version :mid do
    process resize_to_fit: [180, 180]
  end
  version :large do
    process resize_to_fit: [300, 300]
  end
  def extension_white_list
    %w(jpg jpeg gif png)
  end
  def filename
    if original_filename.present?
      extname = Fiile.extname(original_filename)
      "#{Digest::MD5.hexdegest(Time.now)}.#{extname}"
    end
  end
  def manual_crop
    if model.cropping?
      manipulate! do |img|
        img.crop "#{model.crop_w}x#{model.crop_h}+#{model.crop_x}+#{model.crop_y}"
        img
      end
    end
  end
end