Ruby on Railsのフォームから画像をサーバにアップロードするしくみをRubyGems『CarrierWave 』を使って実装します。 またImageMagickを使って画像のリサイズをしたり、フォームのアップロード時に画像サイズのバリデーションにもトライしてみます。
🏀 CarrierWaveの画像アップローダーを作成 ImageMagickのインストール画像の加工を行うためのライブラリImageMagickをインストールします。 Macの場合は次のコマンドをコマンドラインから実行します。
Gemfileの登録Gemfileに以下を追加して、bundle installを実行。
# Image Uploader gem'carrierwave' gem'rmagick' ,require: 'RMagick'
CarrierWaveのアップローダーを作成次のコマンドを実行してCarierWave用のクラスapp/uploaders/image_uploader.rbを生成します。
# scaffold で Productに関する一式を作成 rails g scaffold productname: stringimage: text # アップローダーを作成 rails g uploader image
アップローダーの記述を修正先ほど生成されたimage_uploader.rbを次のように書き換えます。
# app/uploaders/image_uploader.rb class ImageUploader < CarrierWave::Uploader::Base include CarrierWave::RMagick storage:file processconvert: 'jpg' # 保存するディレクトリ名 def store_dir "uploads/#{model.class .to_s.underscore} /#{mounted_as} /#{model.id} " end # thumb バージョン(width 400px x height 200px) version:thumb do process:resize_to_fit => [400 ,200 ] end # 許可する画像の拡張子 def extension_white_list %W[jpg jpeg gif png] end # 変換したファイルのファイル名の規則 def filename "#{Time.zone.now.strftime('%Y%m%d%H%M%S' )} .jpg" if original_filename.present?end end
Modelのカラムにアップローダーを紐付けModelProduct.imageと、アップローダーImageUploaderとをひも付け。
# app/models/product.rb model Product # ↓ 以下を追加 mount_uploader:image , ImageUploader end
view/formへの追加viewのformに以下を追加。
# app/views/products/_form.html.haml form_for(@product)do |f| # ↓ 以下を追加 = f.file_field:image end
view表示側への追記アップロードした画像をviewで表示させる場合は以下を追記してください。
# app/views/products/show.html.haml = image_tag @product.image_url(:thumb )
以下を追加して、テーブルを作成。
bundle exce rake db:migrate
🎉 補足: 画像のサイズのバリデーション アップロードする画像のサイズをチェックするバリデーション(validation)です。今回は幅400px, 高さ400pxより小さい場合にバリデーションでエラーが出るようにします。
まずはバリデーションの記述を追記。
# app/models/product.rb class Product < ActiveRecord::Base# ↓ これらを追記 # ------------------------------------------------------------------ # Validations # ------------------------------------------------------------------ validatedef check_image_dimensions if geometry[:width ]<400 || geometry[:height ]<400 errors.add:image ,'400x400ピクセル以上のサイズの画像をアップロードしてください' end end # ------------------------------------------------------------------ # Public Instance Methods # ------------------------------------------------------------------ def geometry @geometry|| = _geometry end private # ------------------------------------------------------------------ # Private Instance Methods # ------------------------------------------------------------------ def _geometry if image.fileand File.exists?(image.file.file) img =: :Magick : :Image : :read (image.file.file).first {width: img.columns,height: img.rows } end end end
これで、アップロードした画像が幅400px, 高さ400pxより小さい場合はエラーが出ます。
🎃 補足:simple_formでプレビュー表示させる場合 『simple_form 』はformの記述がスッキリするgemです。 このsimple_formとCarrierWaveを連携させる手順です。
Gemfileの登録Gemfileに以下を追加して、bundle installを実行。
# Form Helper gem'simple_form'
プレビュー表示を行うフォーム次のコードを書きます。
# app/inputs/image_preview_input.rb class ImagePreviewInput < SimpleForm::Inputs::FileInput def input # :preview_version is a custom attribute from :input_html hash, so you can pick custom sizes version = input_html_options.delete(:preview_version ) out ='' # the output string we're going to build # check if there's an uploaded file (eg: edit mode or form not saved) if object.send("#{attribute_name} ?" )# append preview image to output out<< template.image_tag(object.send(attribute_name).tap {|o| break o.send(version)if version}.send('url' )) end # allow multiple submissions without losing the tmp version out<< @builder.hidden_field("#{attribute_name} _cache" ).html_safe # append file input. it will work accordingly with your simple_form wrappers (out<< @builder.file_field(attribute_name, input_html_options)).html_safe end end
でもってform 側は次のように書きます。
# app/views/products/_form.html.haml # ↓ こんな感じでコードを修正 = simple_form_for @productdo |f| = f.input:image ,as: :image_preview ,input_html: {preview_version: :thumb }
すると、アップロード済のデータを編集する際に、formでpreview画像が表示されます。
🐡 参考リンク
🖥 VULTRおすすめ 「VULTR 」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTR のヘビーユーザーになので、「ここ 」から会員登録してもらえるとサービス開発が捗ります!