6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年9月7日 現場Rails Chapter7-5-4 ファイルをアップロードしてモデルに添付する

Active Storageとは何?

Railsガイド(Active Storageの概要)には以下のように書かれています。

Active StorageとはAmazon S3Google Cloud Storage、Microsoft Azure Storageなどの クラウドストレージサービスへのファイルのアップロードや、ファイルをActive Recordオブジェクトにアタッチする機能を提供します。development環境とtest環境向けのローカルディスクベースのサービスを利用できるようになっており、ファイルを下位のサービスにミラーリングしてバックアップや移行に用いることもできます。 アプリケーションでActive Storageを用いることで、ImageMagickで画像のアップロードを変換したり、 PDFやビデオなどの非画像アップロードの画像表現を生成したり、任意のファイルからメタデータを抽出したりできます。

今までは、CarrierWaveを使って画像ファイルをアップロード・管理するのが主流でした。しかし、既存のテーブルにカラムを追加するなど、導入するのに手間が掛かりました。そのため、Rails 5.2からActive Storageがデフォルトで導入されました。

Active Storageが提供するメソッド

ActiveStorageを用いることで、さまざまなメソッドが使えるようになります。

attachメソッド・・・IOオブジェクトを渡すことで、対象のオブジェクトに対してファイルを直接紐づけることができます。

@message.image.attach(io: File.open('/path/to/file'), filename: 'file.pdf')

attached? メソッド・・・レシーバーのオブジェクトに画像が紐づいていれば、trueを返し、紐づいていなければfalseを返します。

@message.images.attached?

puregeメソッド・・・オブジェクトと添付ファイルの紐付けを解除する。実行すると、対象のblobファイルとファイルデータがDBから削除されます。

user.avatar.purge

variantメソッド・・・blobから画像を呼び出す際に変換処理を行うことができます。このメソッドを用いるには、gem 'image_processing' を導入する必要があります。

<%= image_tag user.avatar.variant(resize: "100x100") %>

image_tag を使う場合は画像が添付されていないとエラーになってしまうため、if @message.images.attached? で判定メソッドを使って画像が添付されているときだけimage_tag を表示するように使用できます。(画像は添付必須ではない事が多いのではないかと思います)

if @task.image.attached?
  image_tag @task.image
else
  image_tag 'default'
end

※ストロングパラメータにActiveStorageで追加したパラメータを許可することを忘れずに行うとよいでしょう。

CSVファイルとは何?

CSVとは、Comma-Separated Valuesの略で、カンマ区切りのテキストデータという意味です。CSVファイルは、CSV形式で記述されたファイルのことを指します。CSVは各ソフトウェアで共通している形式であり、CSVを使うことで、異なるソフトウェアでのデータ移行が簡単に行える。

CSVの出力

app/models/task.rb

  # どの属性をどの順番で出力するかを定義してcsv_attributesメソッドで要素に属性名の文字列を持つ配列を作成します。
  def.csv_attributes
    ["name", "description", "created_at", "updated_at"]
  end
  # CSV形式でインスタンスの中身を出力できるようにします。
  def self.generate_csv
    CSV.generate(headers: true) do |csv|
      # headers: trueはデータベースの一番上の行をCSVのレコードのタイトルを指定します。
      # csvに上記で定義したcsv_attributesを一行目として代入します。
      csv << csv_attributes
      all.each do |task| 
        # eachでtaskを一つ一つ取り出してtaskの値を代入していきます。
        csv << csv_attributes.map{ |attr| task.send(attr) }
      # mapはcsv_attributesの配列の中身全てに対して処理を行います。
      # task.sendは引数に指定したメソッドを文字列で返します。
      # 文字列として返った属性名の中身をCSVに追加します。
      end
    end
  end

コントローラ内でレスポンスの形式をcsvで指定してあげることで、そのアクションにリクエストが飛んできた時の、レスポンスをcsv形式で返します。

def index
  ~ 略 ~
  respond_to do |format|
    format.html
    format.csv { send_data @tasks.generate_csv, filename: "sample.csv"}
  end
end

generate_csvで生成されたcsv形式のデータをsend_dataメソッドでリクエスト先に返しています(ダウンロード)。 strftimeメソッドは日時データを指定したフォーマットで文字列に変換することができるメソッドです。

blog = Blog.find(1)
# strftimeメソッドを使い指定した形で文字列として出力
blog.created_at.strftime("%Y年%m月%d日")
=> "2019年07月26日"

参照

Railsガイド(Active Storageの概要)
https://railsguides.jp/active_storage_overview.html
CSVファイルとは何?何のために使うの?
https://www.wakarutodekiru.com/blog/tips/578.html