##したいこと
ActiveStorageを使って投稿機能を実装している状態で、ファイルの添付を必須にするバリデーションをかけ、それに対応したseedデータの用意したい。
##前提
- Userと1対多の関係にあるPostモデルがある
- PostにActiveStorageでファイルが紐づけられている
駆け足で説明すると
//UserとPostモデルを作成
$ rails g model User name:string
$ rails g model Post body:text
※ActiveStorageで追加したいファイル用のカラムは作らなくて大丈夫です。
マイグレーションファイルを編集
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.text :body
#外部キーを追加
t.references :user, foreign_key: true
t.timestamps
end
end
end
$ rails db:migrate
アソシエーションの記述
class User < ApplicationRecord
has_many :posts, dependent: :destroy
end
class Post < ApplicationRecord
belongs_to :user
end
ActiveStorageを導入
$ rails active_storage:install
$ rails db:migrate
Postモデルに画像を1つ添付する設定
class Post < ApplicationRecord
belongs_to :user
#追記
has_one_attached :image
end
:image
の部分はファイルの呼び名で自由に指定してよい
参考
- 【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】
- Railsの外部キー制約とreference型について
- 【Rails 5.2】 Active Storageの使い方
##postモデルに画像をの添付を必須にするバリデーションをつける
今回はactivestorage-validatorというgemを使います。
https://github.com/aki77/activestorage-validator
Gemfileを編集
gem 'activestorage-validator'
$ bundle
Postモデルに追記
class Post < ApplicationRecord
has_one_attached :image
belongs_to :user
#追記
validates :image, presence: true, blob: {content_type: :image}
end
エラーメッセージは@post.errors.full_messages
に格納されているので
<ul>
<% @post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
のように書くと表示させることができます。
##seedデータを用意する
まず画像データをapp/assets/images/
に用意します。
WSL(Windows Subsystem for Linux)で画像を用意したい
次にseedを書いていきます。ここハマりました、ポイントとしては
- 一度インスタンスを作成してからattachする
- createではなくnewとsaveを使う
User.Create!(name: "tony")
post = Post.new(
user_id: 1,
body: "foo"
)
post.image.attach(io: File.open("app/assets/images/sample.jpg"), filename: "sample.jpg", content_type: 'image/jpg')
post.save!
参考
【Rails6】seedファイルに画像を追加する(ActiveStorage使用)
Active Storage 3.3 Attaching File/IO Objects
以上です。