22695


下記環境で、アップロードした画像を任意の範囲でcroppingするための処理を実装していたのですが、メインの画像ファイルは意図した通りにcropできました。しかし、versionsでの処理が上手く行かなかったので質問させてください。

  * Rails 4.2.1
  * CarrierWave 0.10.0
  * 試行するためのプロジェクトも公開しています。 
    * <https://github.com/kntmrkm/carrierwave_crop_example>

## 詳細

アップロードした画像はversionを[:mobile]として別途processしているのですが、  
croppingが適用されません。実現したいのはメインのアップロード画像と併せて[:mobile]バージョンもcroppingしたいのです。

### Cropのための記述

app/uploaders/common_uploader.rb

[code]

    class CommonUploader < CarrierWave::Uploader::Base
      include CarrierWave::MiniMagick
    
      def cropper
        return unless model.send("#{mounted_as}_crop_x").present?
        manipulate! do |img|
          crop_x = model.image_crop_x.to_i
          crop_y = model.image_crop_y.to_i
          crop_w = model.image_crop_w.to_i
          crop_h = model.image_crop_h.to_i
          rotation = model.image_rotate.to_i
          crop_value = "#{crop_w}x#{crop_h}+#{crop_x}+#{crop_y}"
    
          img.rotate rotation
          img.crop crop_value
          img = yield(img) if block_given?
          img
    
        end
      end
    
    end
    
[/code]

app/models/user.rb

uploaders/に記述したcropperメソッド内ではattr_accessorの値が取得できないようです。  
（<https://stackoverflow.com/questions/17639405/carrierwave-attributes-that-
are-not-in-the-database-is-always-equal-to-nil>）

なので、他の情報を参考にafter_update時に、croppingメソッドから画像処理を呼び出すようにしました。

[code]

    class User < ActiveRecord::Base
      mount_uploader :image, ::UserImageUploader
    
      attr_accessor :image_crop_x
      attr_accessor :image_crop_y
      attr_accessor :image_crop_w
      attr_accessor :image_crop_h
      attr_accessor :image_rotate
    
      after_update :cropping
    
      private
        def cropping
          if image_crop_x.present?
            image.process!
            #image.cropper
    
            #image.cache_stored_file!
            #image.retrieve_from_cache!(image.cache_name)
            #image.recreate_versions!
            #image.recreate_versions!
          end
        end
    end
    
[/code]

image.process!またはimage.cropperをuser.rb内のcroppingで実行するとcropされます。また、以下のように記述しても可能です。

[code]

    image.cache_stored_file!
    image.retrieve_from_cache!(image.cache_name)
    image.recreate_versions!
    
[/code]

しかし、`app/uploaders/user_image_uploader.rb`に記述している、[:mobile],[:thumb]のバージョンについてはcropできません。

[code]

    class UserImageUploader < CommonUploader
      version :mobile do
    
      end
      version :thumb do
        process quality: 50
      end
    end
    
[/code]

以上が問題の内容なのですが、`image.recreate_versions!`を２度記述するとmobile,thumbのバージョンについてもcropされるようになります。しかし、この場合、外部ストレージの環境（S3など）の際に`NoMethodError
- undefined method`content_length' for nil:NilClass:`が発生してしまいます。

どのように記述すればよいでしょうか？

よろしくお願いいたします。


CC BY-SA 3.0
2015-08-17T19:01:19.663
14546
2016-03-01T08:03:12.020
2017-05-23T12:38:56.467
-1
512
question
ruby-on-rails rubygems carrierwave
CarrierWaveでCrop処理をする際のversionsについて


自己回答です。

バックエンド側でcrop処理することをやめ、フロントエンドでcropした画像データを送ることにしました。

[FormDataを使わずにBlobをアップロード・inputタグに設定する方法はありますか？](https://ja.stackoverflow.com/questions/20169/formdata%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%9A%E3%81%ABblob%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89-input%E3%82%BF%E3%82%B0%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B)


CC BY-SA 3.0
2016-03-01T07:58:58.373
22695
2016-03-01T07:58:58.373
2017-04-13T12:52:38.920
-1
512
14546
answer