📤

CarrierWave 用のカラムが NOT NULL のときのローカルデータの作り方

2024/08/28に公開

ラブグラフでエンジニアをしております横江( @yokoe24 )です!

画像のアップロードに CarrierWave を使っているのですが、
この前ちょっとだけ困ったことがあったので解決方法を記します。

データベースのファイル用カラムが NOT NULL のテーブル

例えばこのようなテーブルがあるとしましょう。

create_table :user_settings,charset: "utf8mb4", collation: "utf8mb4_bin", force: :cascade do |t|
  t.bigint   :user_id,    null: false
  t.string   :avatar,     null: false  # アバター画像
  t.datetime :created_at, null: false, precision: 6
  t.datetime :updated_at, null: false, precision: 6

  t.index :user_id, unique: true
end

add_foreign_key :user_settings, :users, on_update: :cascade

モデルはこのようになっています。

class UserSetting < ApplicationRecord
  mount_uploader :avatar, AvatarUploader

  belongs_to :user

  validates :avatar, presence: true
end

現実では、ユーザー作成時にアバター画像が必ず設定されていないという
作りになっていることはほぼありえないのですが、今回はそういう実装になっていたとしてください。

このとき、ダミーデータとしてユーザーを作りたい場合は大変です。

user = User.first
UserSetting.create!(user: user, avatar: "")

=> バリデーションに失敗しました: avatarを入力してください (ActiveRecord::RecordInvalid)

ってな感じでバリデーションエラーになってしまいます。

avatar カラムの値はどのように設定すればいいのでしょうか・・・?

解決方法

いったい avatar カラムにどんな String(文字列)を入れればいいのか……と最初は悩んだのですが、
解決方法は実はとてもカンタンで、
File.open メソッドを使って File オブジェクト を作成すればOKです!

ローカルのファイルを File.open で開いて、avatar カラムに代入しましょう。

file = File.open("app/assets/images/dummy_avatar.png")

user = User.first
UserSetting.create!(user: user, avatar: file)

なにか適当な画像ファイルを
app/assets/imagesdummy_avatar.png という名前で置いて、
それを読み込むようにしています。

全部同じ画像になってしまいますが、以下のように一度に大量の UserSetting を作ることも可能です。

file = File.open("app/assets/images/dummy_avatar.png")

User.first(100).pluck(:id).each do |user_id|
  UserSetting.create!(user_id: user_id, avatar: file)
end

このようにして、CarrierWave のためのカラムがあっても
初期値をカンタンに設定できることがわかりました!

ラブグラフのエンジニアブログ

Discussion