Rails 5.2 ActiveStorage上传图片以及如何按用户裁剪图片

时间:2018-08-07 09:15:19

标签: ruby-on-rails rails-activestorage

一旦我使用carrierwaveJcrop上传和裁剪用户图片,它就会很好用。用户可以免费剪裁,然后上传图片。但是现在我想将上传方式从carrierwave更改为ActiveStorage。这时我还想免费剪裁图片。那我该如何更改密码?非常感谢!

我在gems中的角色:

gem 'rails', '~> 5.2'
gem 'mini_magick'

# gem 'carrierwave', '~> 1.2', '>= 1.2.2'**(No use in ActiveStorage)**

我的用户models的一部分:

# user.rb

has_one_attached :picture
has_one_attached :avatar

attr_accessor :remember_token, :activation_token, :crop_x, :crop_y, :crop_w, :crop_h

after_update :crop_picture

def crop_picture
    picture.recreate_versions! if crop_x.present?
end
# mount_uploader :picture, PictureUploader**(No use in ActiveStorage)**
  # mount_uploader :avatar, PictureUploader**(No use in ActiveStorage)**

我的user_controllers的一部分:

 def new
    @user = User.new
  end

 def create
    @user = User.new(user_params) 
    if @user.save
      log_in @user
      flash[:success] = "Almost success"
      redirect_to confirmation_path(@user.name)
    else
      flash.now[:danger] = 'Failure'
      render :new
    end
  end

def update
    @user = User.friendly.find(params[:id])
    if @user.update_attributes(user_params)
      if params[:user][:picture].present?
        render :crop
      else
        redirect_to @user
        flash[:success] = "Update success"
      end
    else
      flash[:warning] = "Update failue"
      render :edit
    end
  end

private

  def user_params
    params.require(:user).permit(... :avatar, :picture)
  end

我的crop.html.erb

<div class="container">
  <div class="col-md-12 pbt20 bgCo">
    <div class="col-md-8">
      <h4 class="pageItemTitle mbt20">Crop Picture</h4>
      <%#= image_tag @user.picture.url(:large), :id => "user_preview" %>
      <%= image_tag(@user.picture.variant(combine_options: { gravity: 'Center', crop: '600x800+0+0' }),width: 600,id: "cropImage")  %>
    </div>
    <div class="col-md-4">
      <h4 class="pageItemTitle mbt20">Crop Preview</h4>
      <div style="width:160px; height:160px; overflow:hidden; border-radius: 50%;">
        <%= image_tag @user.picture, :id => "user_preview" %>
      </div>
      <div class="crop-footer pull-right mbt20 pbt20">
        <%= form_for @user do |f| %>
          <% %w[x y w h].each do |attribute| %>
            <%= f.hidden_field "crop_#{attribute}" %>
          <% end %>
          <%= link_to "Close", @user,  class: "btn btn-default mr10" %>
          <%= f.submit "Crop", class: "btn btn-primary" %>
        <% end %>
      </div>
    </div>

  </div>
</div>

我的crop.js.coffee

jQuery ->
  new PictureCropper()

class PictureCropper
  constructor: ->
    $('#cropImage').Jcrop
      aspectRatio: 1
      setSelect: [0, 0, 400, 400]
      onSelect: @update
      onChange: @update

  update: (coords) =>
    $('#user_crop_x').val(coords.x)
    $('#user_crop_y').val(coords.y)
    $('#user_crop_w').val(coords.w)
    $('#user_crop_h').val(coords.h)
    @updatePreview(coords)

  updatePreview: (coords) =>
    $('#user_preview').css
      width: Math.round(160/coords.w * $('#cropImage').width()) + 'px'
      height: Math.round(160/coords.h * $('#cropImage').height()) + 'px'
      marginLeft: '-' + Math.round(160/coords.w * coords.x) + 'px'
      marginTop: '-' + Math.round(160/coords.h * coords.y) + 'px'

我的picture.uploader :(在ActiveStorage中不使用)

class PictureUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  storage :file

  def store_dir
    "uploaders/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :large do
    process :crop
    resize_to_limit(600, nil)
  end

  def crop
    if model.crop_x.present?
      resize_to_limit(600, nil)
      manipulate! do |img|
        x = model.crop_x.to_i
        y = model.crop_y.to_i
        w = model.crop_w.to_i
        h = model.crop_h.to_i
        img.crop([[w, h].join('x'),[x, y].join('+')].join('+'))
      end
    end
  end

  def extension_white_list
    %w(jpg jpeg gif png)
  end

  def filename
    s = "#{model.id}"
    t = s.to_i * 365
    t.to_s + ".jpg" if original_filename
  end

end

如果我将上传方法从carrierwave更改为ActiveStorage,并且此时我还希望按用户释放剪贴画。那我该如何更改密码?非常感谢!

1 个答案:

答案 0 :(得分:1)

我在PostgreSQL中将作物坐标存储为名为crop_settings json字段。

以下是用于生成缩略图变体和裁剪图像变体的工作代码。

#Event.rb

class Event < ApplicationRecord
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h

  has_one_attached :cover_image
  before_save :check_cropping 

  def check_cropping
    self.crop_settings = {x: crop_x, y: crop_y, w: crop_w, h: crop_h} if cropping?
  end 

  def cropping?
    !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
  end

  def cropped_image
    if cover_image.attached?
      if crop_settings.is_a? Hash
        dimensions = "#{crop_settings['w']}x#{crop_settings['h']}"
        coord = "#{crop_settings['x']}+#{crop_settings['y']}"
        cover_image.variant(
          crop: "#{dimensions}+#{coord}"
        ).processed
      else
        cover_image
      end
    end
  end

  def thumbnail(size = '100x100')
    if cover_image.attached?
      if crop_settings.is_a? Hash
        dimensions = "#{crop_settings['w']}x#{crop_settings['h']}"
        coord = "#{crop_settings['x']}+#{crop_settings['y']}"
        cover_image.variant(
        crop: "#{dimensions}+#{coord}",
        resize: size
        ).processed
      else
        cover_image.variant(resize: size).processed
      end
    end
  end
end

视图/事件/show.html.erb

...
<div>
  Original Image:
  <%= image_tag(@event.cover_image) if @event.cover_image.attached? %>
</div>
<div>
  Cropped Image:
  <%= image_tag(@event.cropped_image) if @event.cropped_image %>
</div>
<div>
  Thumbnail:
  <%= image_tag(@event.thumbnail) if @event.thumbnail %>
</div>
 ...

enter image description here

如果该变体是先前创建和存储的,则将使用它而不是重新创建。

enter image description here