質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

3693閲覧

CarrierWave + RMagickを使って画像とPDFをアップロードしたい

zin2

総合スコア21

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

2クリップ

投稿2018/10/09 12:20

編集2018/10/13 23:30

概要

Ruby On Rails 5 で投稿機能を作っています。
アップローダーはCarrierWave、投稿画像についてはサムネイル化したかったのでRMagickを導入しています。
かかる中、以下のような設定をしたことで、pdfファイルのアップロードができなくなり詰まってしまいました。

やりたいこと

carrierWaveを使って画像、PDFをアップロードできるようにしたい。ただし、画像についてはRMagickを使ってサムネイル化させたい。

現状

RMagickを使わない場合(サムネイル化しない)、はうまく機能しています。

現状のアップローダーの設定は以下の通りです。

ArticleUploader

1class ArticleUploader < CarrierWave::Uploader::Base 2 3 include CarrierWave::RMagick 4 5 # サムネイルを生成する設定 6 version :thumb do 7 process :resize_to_limit => [300, 300] 8 end 9 10 # jpg,jpeg,gif,png pdfしか受け付けない 11 def extension_white_list 12 %w(jpg jpeg gif png pdf) 13 end 14 15 protected 16 def secure_token 17 var = :"@#{mounted_as}_secure_token" 18 model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) 19 end 20 21 if Rails.env.production? 22 storage :fog 23 else 24 storage :file 25 end 26 27 def store_dir 28 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 29 end 30 31 def cache_dir 32 "#{Rails.root}/tmp/uploads" 33 end 34 35end 36

PDFがアップロードできない原因と解決方法の自己考察

上記コード内の「#サムネイルを生成する設定」が効いてしまって画像以外のアップロードができないようです。

このため、
該当箇所を拡張子が(jpg jpeg gif png)なら「#サムネイルを生成する設定」を有効、
拡張子が(pdf)なら「#サムネイルを生成する設定」を無視する、
といったような、if文を作れば良いのでは?と考えています。

しかしながら、この条件式の作り方がわからず困っております。
良い解決策がございましたらご教授いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まだまだ初学者なので、良い回答が出せるかどうかわかりませんが…。
私はgemのメソッドが自分の思った通りに動作してくれない場合、そのメソッドをオーバーライドすることにしています。

まずは以下にサンプルコードを記載させていただきますね。

ArticleUploader

1class ArticleUploader < CarrierWave::Uploader::Base 2 3 include CarrierWave::RMagick 4 5 # サムネイルを生成する設定 6 version :thumb do 7 process :resize_to_limit => [300, 300] 8 end 9 10 #以下の記述を追記し、resize_to_limitをオーバーライド 11 def resize_to_limit(width, height) 12 if File.extname(original_filename) == '.pdf' 13 width = dimension_from width 14 height = dimension_from height 15 manipulate! do |img| 16 geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry) 17 new_img = img.change_geometry(geometry) do |new_width, new_height| 18 img.resize(new_width, new_height) 19 end 20 destroy_image(img) 21 new_img = yield(new_img) if block_given? 22 new_img 23 end 24 end 25 end 26 #ここまで 27 28 # jpg,jpeg,gif,png pdfしか受け付けない 29 def extension_white_list 30 %w(jpg jpeg gif png pdf) 31 end 32 33 protected 34 def secure_token 35 var = :"@#{mounted_as}_secure_token" 36 model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) 37 end 38 39 if Rails.env.production? 40 storage :fog 41 else 42 storage :file 43 end 44 45 def store_dir 46 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 47 end 48 49 def cache_dir 50 "#{Rails.root}/tmp/uploads" 51 end 52 53end

さて、こちらの記述で何が行われているのか、簡単に説明させていただきますね。
画像のリサイズに使われているresize_to_limitCarriawave/lib/carrierwave/processing/rmagick.rbで定義されているメソッドです。
このファイルに記載されているメソッドを使えるようにするためにinclude CarrierWave::RMagickという記載があるわけです。

では、ここからメソッドのオーバーライドの話に映ります。
carrierwaveuploader(github)
上記のURLはCarrierwaveの本体のコードがしまってあるページです。
こちらページの/lib/carrierwave/processing/rmagick.rbの一部に以下のような記載があります。

rmagick

1def resize_to_limit(width, height) 2 width = dimension_from width 3 height = dimension_from height 4 manipulate! do |img| 5 geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry) 6 new_img = img.change_geometry(geometry) do |new_width, new_height| 7 img.resize(new_width, new_height) 8 end 9 destroy_image(img) 10 new_img = yield(new_img) if block_given? 11 new_img 12 end 13end

これが、今回オーバーライドすべきメソッドになります。
この文頭にif File.extname(original_filename) == '.pdf'を追加することによって、拡張子がpdfの場合にのみresize_to_limitの処理を実行することができるようになります。
…なる、はず、、です……。
ちなみにextnameは、rubyにおいて、ファイルの拡張子を取得ためのメソッドですね。
詳しい内容に関しては以下のURLに乗っているので、ご参考まで。
extnameに関するドキュメント

方向性としては間違っていないと思うのですが、正直私も自信がありません。
こちらの回答がzin2さんのお役に立てることをお祈りしております。
よろしくお願いいたします。

投稿2018/10/22 02:46

take77

総合スコア130

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zin2

2018/11/13 04:30

また違うエラーが出ており、まだ解決はできていないですが、理論的で丁寧なご説明、ありがとうございました。もう少し検討してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問