LoginSignup
7
1

More than 3 years have passed since last update.

【Rails】PDFをダウンロードできる状態で投稿する方法

Last updated at Posted at 2021-04-14

はじめる前に:Cloudinaryに登録

様々なファイルを投稿するとき、どうしたらいいのかわからなかったので、画像投稿を参照してPDFを投稿してみました。

このリンクから登録をはじめましょう。
https://cloudinary.com/
右上のsign up for freeを押すと、登録画面に飛びます。

手順

Step1 ファイル投稿機能のためにMVCを準備

適当なファイルを使って、作っていきます。
今回は、Topicモデルを使っていきます。

Topicsテーブルにカラムを追加

今回はファイルだけを投稿するためのアプリケーションなので、pdfカラムをString型で追加します。
(ファイルを保存するときにString型で指定するのはそういうものだと思っちゃいましょう)

今回はTopicsテーブルにstring型のpdfカラムを追加するので、

ターミナル
rails generate migration AddPdfToTopics pdf:string

と打ち込んで実行します。
すると、以下のようなマイグレーションファイルがタイムスタンプ付きで自動生成されます。

db/migrate/20××××××××××_create_topics.rb
class AddPdfToTopics < ActiveRecord::Migration[6.0]
  def change
    add_column :topics, :pdf, :string
  end
end

書き込んだら、ターミナルでmigrateします。ターミナルで以下の操作を行いましょう。

$ rails db:migrate

これで、Topicモデルに、pdfという名前の、string型のカラムが追加できました。

Viewの作成

まず、index.html.erbに以下のように追加で記述してください。

app/views/topics/index.html.erb
    <% @topics.each do |t| %>

        <!--ここから-->
        <a href="<%= image_url t.pdf_url %>" target="_blank">
                <div class="post2-2"> 
                    <object data="<%= image_url t.pdf_url %>" type="application/pdf"></object>
                </div>
            </a>
        <!--ここまで-->

        <%= t.body %>
        <%= t.created_at %>

      </div>
    <% end %>
  </div>

実はデータベースにはファイルは保存されておらず、代わりにファイルが置かれる住所が保存されます。なのでt.image_urlのような書き方になります。

次にtopics controllerの一番下に以下のような記述があると思うので、それに「:pdf」の記述を付け加えましょう。

topics_controller.rb
# 割愛

private

def topic_params
  params.require(:topic).permit(:body, :pdf)
end

これをしておかないと、pdfのパラメータが取得できず、投稿ができません。

またnew.html.erbに以下を追加で記述してください。

app/views/topics/new.html.erb

<%= form_for @topic do |f| %>
  <div class="field">
    <%= f.label :body %>
    <%= f.text_field :body, :size => 140 %>
  </div>

  <!--ここから-->
  <div class="field">
    <%= f.label :pdf %>
    <%= f.file_field :pdf %>
  </div>
  <!--ここまで-->

  <%= f.submit "投稿" %>
<% end %>

これはファイルを投稿するためのボタンを実装してくれるためのコードです。

file_fieldの場合は、以下の図のようなformが作られます。
ここにユーザーが投稿したいファイルを投稿することになります。
スクリーンショット 2019-10-19 20.32.34.png
これで下準備は終わりました。次のStepからは実際のファイル投稿機能を実装していこうと思います。

Step2. ファイル投稿機能

早速ここからファイル投稿機能を導入していこうと思います。

gemの追加

今回はcloudinary、carrierwave、dotenv-railsというgemを使っていきます。Gemfileの一番下に以下を追加しましょう。

Gemfile
gem 'carrierwave' , '~> 1.3' ,  '>= 1.3.1'
gem 'cloudinary'
gem 'dotenv-rails'

そしたらターミナルで

ターミナル
$ bundle install

と打ちこんでインストールします。

アップローダーの作成

CarrierWaveのジェネレーターでアップローダーを作成します。以下のコマンドをターミナルに打ち込みましょう。

ターミナル
$ rails g uploader Pdf

uplpder の後ろは、先程追加したカラム名を入れてください。

モデルの修正

Topicモデルを以下のように修正します。

app/models/topic.rb
class Topic < ApplicationRecord

# 追記ここから
  mount_uploader :pdf, PdfUploader
# 追記ここまで

end

mount_uploader :pdf, PdfUploaderはファイルを指定の場所に保存することを表します。

次に保存場所を指定するアップローダの設定です。

app/uploaders/pdf_uploader.rbの6~8行目を変更しましょう。

app/uploaders/pdf_uploader.rb
  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

上記を下図のように変えます。

app/uploader/pdf_uploader.rb
  # Choose what kind of storage to use for this uploader:
  if Rails.env.production?
    include Cloudinary::CarrierWave
    CarrierWave.configure do |config|
      config.cache_storage = :file
    end
  else
    storage :file
  end
  # storage :fog

cloudinaryは外部のストレージサービスです。本番環境(リリース後=production)ではcloudinaryにファイルが保存され、それ以外(開発環境=ローカル)では自分のpcに保存されます。(publicフォルダー内に保存されます)

APIキーの非公開

Cloudinaryの各アカウントには「Cloud name」、「API Key」、「API Secret」というアカウント固有の秘密のIDのようなものが付与されています。
この情報は非常に機密性が高く決して外部に漏らしてはいけない情報なので、これらの値が間違って公開されないような処理を施す必要があります。
のでこの節ではWebサービスを公開した時にそれらの値を公開しないようなコードを書いていくことにします。

三つの値は以下から確認することができます。
Cloudinaryマイページ

Cloudinary_Management_Console_-_Dashboard_png.png

.envというファイルをアプリケーションディレクトリ(appやdbやGemfileがあるディレクトリ)に自分で作成します。
以下の図のようになっていればオッケーです。
※vendorフォルダーの中ではないので注意してください。

スクリーンショット_2018-10-17_2_03_28.png

次に作成した.envファイルに以下を入力します。

.env
CLOUD_NAME=q0w9e8r7t6yu5  #←この値は人によって違います!!
CLOUDINARY_API_KEY=123456789012345 #←この値は人によって違います!!
CLOUDINARY_API_SECRET=1a2s3d4f5g6h7j8k9l0a1s2d4f5g6h1q #←この値は人によって違います!!

ここで「=」の後のそれぞれの値は先ほどのCloudinaryのマイページで取得したキーに書き換えておいてください(自分が取得したキーは絶対他言しないように!!また数字は個々人によって変わります)。
また、書き換える際は、コメントアウト部分を削除してください!

 最後に隠しておきたいデータを定義した.envファイルをみんなに公開してしまっては意味が無いのでこのファイルは公開しないようにします。アプリケーションディレクトリにある.gitignoreに下記を追加します。
※もし.gitignoreファイルがない場合はアプリケーションディレクトリーにて作りましょう!

.gitignore
# 省略

/.env

これでOKです!

APIキーの利用

最後の手順です!
まずはconfigフォルダにcloudinary.ymlファイルを作成してください。

スクリーンショット_2019_10_20_1_11.png

config/cloudinary.ymlに以下のようにそのままコピペしてください。

config/cloudinary.yml

development:
  cloud_name: <%= ENV['CLOUD_NAME'] %>
  api_key: <%= ENV['CLOUDINARY_API_KEY'] %>
  api_secret: <%= ENV['CLOUDINARY_API_SECRET'] %>
  enhance_image_tag: true
  static_file_support: false
production:
  cloud_name: <%= ENV['CLOUD_NAME'] %>
  api_key: <%= ENV['CLOUDINARY_API_KEY'] %>
  api_secret: <%= ENV['CLOUDINARY_API_SECRET'] %>
  enhance_image_tag: true
  static_file_support: false
test:
  cloud_name: <%= ENV['CLOUD_NAME'] %>
  api_key: <%= ENV['CLOUDINARY_API_KEY'] %>
  api_secret: <%= ENV['CLOUDINARY_API_SECRET'] %>
  enhance_image_tag: true
  static_file_support: false

これでAPIキーを非公開にしたまま利用することができました。

PDFのダウンロード

PDFをダウンロードするときは、表示されているファイルを右クリックして、保存することができます!

ファイル内のPDFを表示させる

app/assets/images内に、PDFファイルを入れます。

スクリーンショット 2021-04-16 20.11.26.png

その後、表示したいページのviewに、下の文章を入れます!

<object data="../../../assets/07.pdf" type="application/pdf" width="100%" height="100%"></object>
7
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1