
updated on 2019-07-11
今までは画像やファイルを保存したいときは、paperclipを使っていましたが、rails5.2からはactive storageが推奨されている様です。
そして腰抜かすくらい簡単に
導入できてしまいます
早速やっていきます!!
1. active_storageのインストール
$ rails active_storage:install $ rails db:migrate
active_storageの設定ファイルをインストールした後、マイグレーションを実行することでactive_storage_blobsとactive_storage_attachmentsという名前のテーブルが2つ生成されます。
Blobはファイル名、ファイルの種類、バイト数、誤り検出符号などのメタデータを保持するモデルで、Attachmentモデルは、BlobオブジェクトとActive Recordオブジェクトを紐付けるための中
テーブルですが、全くいじる必要のないモデルなので、特に覚えなくても結構です。
2. model生成
$ rails g model Article title:string body: text $ rails db:migrate
3. 実装
article.rb
# article.rb class Article < ApplicationRecord has_one_attached :image end
:imageはファイルの呼び名で、:photo、:avatar、:profileなど、好きなものを指定してください。
ここで指定した image は、articlesテーブルのカラムの様な扱いになりますが、imageテーブルなどを作る必要はないです。Active Storageは裏側でBlobとAttachmentモデルを使って、勝手に
article.imageを使えるようにしてくれます。
articles_controller.rb
class CommentsController < ApplicationController
before_action :find_article, only: [:edit, :update, :show, :destroy]
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
flash[:notice] = "保存しました"
redirect_to article_path(@article)
else
flash[:alert] = "エラーが発生しました"
render :new
end
end
def show
end
def edit
end
def update
if @article.update(article_params)
flash[:notice] = "更新しました"
redirect_to article_path(@article)
else
flash[:alert] = "エラーが発生しました"
render :edit
end
end
def destroy
if @article.destroy
flash[:notice] = "削除しました"
redirect_to articles_path
else
flash[:alert] = "エラーが発生しました"
end
end
# imageは、titleフィールドやbodyフィールドと同じ様に、articlesテーブルのカラムの様な扱いをする
private
def article_params
params.require(:article).permit(:title, :body, :image)
end
def find_article
@article = Article.find(params[:id])
end
endarticles/_form.html.erb
<%= form_with model: article, local: true do |f| %>
<% if @article.errors.any? %>
<div id="error_explanation">
<h2><%= "#{pluralize(@article.errors.count, "error")} により保存できませんでした" %></h2>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_area :title %><br>
<%= f.file_field :image %><br>
<%= f.text_area :body %><br>
<%= f.submit %>
<% end %>new.html.erb
<h2>新規投稿</h2> <%= render "articles/form", artilce:@article %>
edit.html.erb
<h2>編集</h2> <%= render "articles/form", artilce:@article %>
show.html.erb
<div class="col-sm-11 col-sm-offset-1 col-xs-12"> <h2 class="text-center"><%= @article.title %></h2> <div class="text-center"> <% if @article.image.attached? %> <%= image_tag @article.image, :alt => "イメージ", width: '30%', height: '30%' %> <% end %> </div> <h5 class="text-center"><%= @article.created_at.strftime('%b %d, %Y') %></h5> <div class="fr-view"> <%= raw @article.body %> </div> </div>
<% if @article.image.attached? %>
<%= image_tag @article.image, :alt => "イメージ", width: '30%', height: '30%' %>
<% end %>
の部分の :alt => "イメージ", width: '30%', height: '30%'は好きに変えてください。
これでactive_storageへの投稿、更新、削除が完成しました
しかし...active_storageは複数のファイルを保存することもできますので、そちらも紹介します。
article.rb
# article.rb class Article < ApplicationRecord # has_one_attached :image has_many_attached :images end
articles_controller.rb
class CommentsController < ApplicationController
before_action :find_article, only: [:edit, :update, :show, :destroy]
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
flash[:notice] = "保存しました"
redirect_to article_path(@article)
else
flash[:alert] = "エラーが発生しました"
render :new
end
end
def show
end
def edit
end
def update
if @article.update(article_params)
flash[:notice] = "更新しました"
redirect_to article_path(@article)
else
flash[:alert] = "エラーが発生しました"
render :edit
end
end
def destroy
if @article.destroy
flash[:notice] = "削除しました"
redirect_to articles_path
else
flash[:alert] = "エラーが発生しました"
end
end
# imageは、titleフィールドやbodyフィールドと同じ様に、articlesテーブルのカラムの様な扱いをする
private
def article_params
# params.require(:article).permit(:title, :body, :image)
params.require(:article).permit(:title, :body, :images)
end
def find_article
@article = Article.find(params[:id])
end
endarticles/_form.html.erb
<%= form_with model: article, local: true do |f| %>
<% if @article.errors.any? %>
<div id="error_explanation">
<h2><%= "#{pluralize(@article.errors.count, "error")} により保存できませんでした" %></h2>
<ul>
<% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.text_area :title %><br>
<!-- <%= f.file_field :image %><br> -->
<%= f.file_field :images, multiple: true %><br>
<%= f.text_area :body %><br>
<%= f.submit %>
<% end %>show.html.erb
<div class="col-sm-11 col-sm-offset-1 col-xs-12"> <h2 class="text-center"><%= @article.title %></h2> <div class="text-center"> <!-- <% if @article.image.attached? %> <%= image_tag @article.image, :alt => "イメージ", width: '30%', height: '30%' %> <% end %> --> <% if @article.images.attached? %> <% @article.images.each do |image| %> <%= image_tag image %> <br> <% end %> <% end %> </div> <h5 class="text-center"><%= @article.created_at.strftime('%b %d, %Y') %></h5> <div class="fr-view"> <%= raw @article.body %> </div> </div>
new.html.erb(変更なし)
<h2>新規投稿</h2> <%= render "articles/form", artilce:@article %>
edit.html.erb(変更なし)
<h2>編集</h2> <%= render "articles/form", artilce:@article %>
THAT'S ALL RIGHT!!
ちなみに、今回は使わなかったものの、urlを生成したりプレビュー、ダウンロードリンクをするときは以下を使用
<%= link_to 'プレビュー', rails_blob_path(article.image, disposition: 'preview') %><%= link_to 'ダウンロード', rails_blob_path(article.image, disposition: "preview") %>例) Rails.application.routes.url_helpers.url_for(Article.find(145).image) * url_for も rails_blob_path と同じ!config/environments/development.rb
# ...
# Store uploaded files on the local file system (see config/storage.yml for options)
config.active_storage.service = :local
# ...config/environments/production.rb
# ...
# Store uploaded files on the local file system (see config/storage.yml for options)
config.active_storage.service = :local
# ...defaultの local とは、 config/storage.yml で定義された保存先の名前
config.active_storage.service = :localを :amazon, :google, :microsoft のいづれかと置き換えて、config/storage.ymlの方に、必要な認証情報などの値を入力します。
config/storage.yml
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
# amazon:
# service: S3
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
# region: us-east-1
# bucket: your_own_bucket
# Remember not to checkin your GCS keyfile to a repository
# google:
# service: GCS
# project: your_project
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
# bucket: your_own_bucket
# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
# microsoft:
# service: AzureStorage
# storage_account_name: your_account_name
# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
# container: your_container_namedefaultの保存先の local は、使用するサービスが Disk (ローカルディスク)に設定れていて、保存先がrailsアプリ直下の/storageディレクトリに指定されています。
保存先に応じてコメントを解除してください。
amazon: を使用するあなたは gem aws-sdk-s3
goolge: を使用するあなたは gem google-cloud-storage
microsoft: を使用するあなたは gem azure-storage をGemfileに追記
なお、アクセスキーなどの機密情報は、Rails Credentials(暗号化して保存するためのRails新機能)を使って入力!!
$ EDITOR=vim rails credentials:edit
i を押す
実際の値を入れていく
escを押す
ZZ を押す
保存完了
(入力した内容はconfig/master.keyを用いて暗号化され、config/credentials.yml.encが生成されます)
$ rails credentials:show で確認できるgem "aws-sdk-s3", require: false
$ bundle installと叩きます。
config/environments/production.rb
# ファイル保存先を:localから:amazonに変更 config.active_storage.service = :amazon
config/environments/development.rb
# 開発環境(development)でAmazon S3の動作を確認したい場合はこちらの方も変更しましょう config.active_storage.service = :amazon
config/storage.yml
# 以下の部分をコメント解除する amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> region: ap-northeast-1 # これは日本の地域コード bucket: my_bucket_name # 自分で作成したS3のバケットの名前
$ EDITOR=vim rails credentials:edit
(エディタはVim(vim)かAtom(atom)かVSCode(code)かSublimeText(subl))aws: access_key_id: 123 #ここに自分のアクセスキーIDをコピペ secret_access_key: 456 #ここに自分のシークレットアクセスキーをコピペ
Vim: iで入力開始、esc → ZZで終了
$ rails credentials:show
で内容を確認できる以上でs3にアップロードされるようになりました。s3がこんなに簡単に使えてしまうことが驚き栗の木超ラッキーです!
Credentialsを使用する場合
config/credentials.yml.encの中身を復号化するために必要なconfig/master.keyファイルを本番環境にも配置する必要があります。しかし、master.keyはセキュリティ上, .gitignore されてあり、Gitリポジトリをそのままデプロイする本番環境(Herokuなど)の場合は、master.key の中身をコピーして、環境変数 RAILS_MASTER_KEY としてセットしなければいけません。ちなみに、Herokuをお使いの場合は $ heroku config:set RAILS_MASTER_KEY=123で環境変数を用意できます。
参考文献 こちらの方