経緯
railsにてcloudinaryとcarrierwaveを用いて画像投稿を実装していたのですが、どうやら最近carrierwaveが上手く動いていないようでローカルにそのまま画像が保存されたり、Errno::EACCES in HogesController#create Permission denied @ apply2files -
の様なエラーが出てるようで。。。。
Active Storageを利用すれば無事投稿が出来たので備忘録として残しておきます。
本記事の想定
- cloudinaryのアカウント登録が完了している
- 投稿機能が実装済み
- 環境変数は
gem 'dotenv-rails'
で管理
※rails6.1.7 ruby3.0.4を使用しています。
(rails7.1.3 ruby3.3でも動作確認済み)
実装
Active Storageの詳しい仕様ついては公式ドキュメントで確認して下さい。
Active Storageの導入
$ rails active_storage:install
$ rails db:migrate
実際にアップロードしたファイルが保存されるテーブルactive_storage_blobs
や、active_storage_attachments
という中間テーブルが作成されます。
config/storage.ymlの編集
config/storage.ymlファイルにCloudinary用の設定を追加します。
cloudinary:
service: Cloudinary
cloud_name: <%= ENV['CLOUD_NAME'] %>
api_key: <%= ENV['CLOUDINARY_API_KEY'] %>
api_secret: <%= ENV['CLOUDINARY_API_SECRET'] %>
環境変数名は.env
に書かれている内容を合わせてください。
インデントは編集しないようにしてください、
development.rb production.rbの編集
開発環境での画像保存を設定する場合development.rb、本番環境の場合はproduction.rbを編集してください。
変更前
config.active_storage.service = :local
変更後
config.active_storage.service = :cloudinary
production.rbも同様に編集してください。
Gemのインストール
gem 'activestorage-cloudinary-service'
gem 'cloudinary'
をまだ入れてない人はgem 'cloudinary'
も入れてください!
bundle install
モデルの編集
画像を保存するカラムを用意します。テーブルに新しくカラムを追加する必要はなく、投稿機能を実装しているモデル(本記事ではTweetモデル)に画像を保存する用のカラム(本記事ではphoto)を記述するだけで大丈夫です。
既にテーブルに作成しているカラム名とは違う名前を記述してください。
例えば、「imageカラムを既に作ってるのでそれを使おう!」みたいな事が出来ないという事です。
class Tweet < ApplicationRecord
has_one_attached :photo #追記
end
わざわざテーブルにカラムを追加する必要がないのは便利ですね。
view,controllerの編集
コントローラ(本記事の場合はtweets)にてストロングパラメータにphotoカラムを追加
private
def tweet_params
params.require(:tweet).permit(:title, :body, :photo) #photoを追加
end
投稿と表示のviewファイルを編集
<%= form_for @tweet do |f| %>
<div class="field">
<%= f.label :photo %> #追記
<p><%= f.file_field :photo %></p> #追記
</div>
<%= f.submit "投稿する" %>
<% end %>
<% @tweets.each do |t| %>
#追記ここから
<% if t.photo.attached? %>
<%= image_tag t.photo, size: '250x200'%>
<% end %>
#追記ここまで
<% end %>
あとがき
実装は以上ですお疲れ様でした。
本記事では一つの画像を投稿する方法のみを扱いましたが、複数画像を投稿する方法もあるので是非トライしてみてください。
以下、お世話になった記事です。ありがとうございました。