Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@shibadog39

Shrineのimage_dataを含むモデルのFactoryの作り方

More than 1 year has passed since last update.

(編集しようとしたら誤って削除してしまったので再投稿しました)

railsの画像アップロードライブラリshrineを用いた場合の、FactoryBotのFactoryの書き方について悩んだポイントがあったので書いておきます

前提

登場するModel

  • Area
column type memo
name string require
  • Shop
column type memo
area bigint require
logo bigint require
name string require
  • Logo
column type memo
area bigint require
name string require
image_data text require

Area has_many Shop
Area has_many Logo
Shop belongs_to Logo

各Shopはエリアに登録されているロゴを使用できるイメージです。

悩んだこと

logoのファクトリーのimage_data カラムをどう書くべきなのか悩みました。

spec/factories/logos.rb
FactoryBot.define do
  factory :logo do
    area
    sequence(:name) { |i| "logo#{i}" }
    image { #この部分!! }
  end
end

もともとは↓のように書いていたのですが、これだとlogoのテストデータが作成されるたびにファイルへアクセスするためRSpec全体の実行時間に大きな影響を与えていました。


image { File.open("#{Rails.root}/spec/fixtures/img/example.png") }

RSpec実行時間

Factory追加前→ 27s
追加後 →1min 3s

shopが作られるたびにFactoryBotによってlogoも自動で作られるのだから遅くなるのは当たり前ですね

試したこと

適当な文字列をつっこむ

image_data { 'sample' }

結果
imageを実際に使うテストにて

JSON::ParserError:765: unexpected token at 'sample'

それはそう。。

fixture_file_upload使ってみる

fixture_file_uploadについて

この記事ではfixture_file_upload使ったらFile.openより相当早い結果になっているので期待大!

image { fixture_file_upload("#{Rails.root}/spec/fixtures/img/example.png", 'img/png') }

結果
テストはすべてpass!
ただし

Finished in 1 minute 9.24 seconds (files took 15.67 seconds to load)

File.openのときと変わらないくらい時間かかってる。。
使い方がおかしい?

最終的に

ファイルアクセスではなく架空のcacheを作成してみる

Shrineのuploaded_fileメソッドを用いてキャッシュの状態でファイルが上がっていることにする作戦

factory :logo do
    area
    sequence(:name) { |i| "logo#{i}" }
    image_data { Shrine.uploaded_file(
      'id' => SecureRandom.hex(8),
      'storage' => 'cache',
      'metadata' => { 'mime_type' => 'image/jpeg', 'size' => 1.megabyte }).to_json }
  end

結果

Finished in 31.04 seconds

いいじゃん!!

参考にしたページ
https://stackoverflow.com/questions/44812403/rails-testing-file-upload-validation-shrine-gem-at-model-spec

補足

最終型において image ではなく image_data を使っている理由について書きます。

はじめはFile.openと同じように下記のように書いていたんですが、

image { Shrine.uploaded_file(
      'id' => SecureRandom.hex(8),
      'storage' => 'cache',
      'metadata' => { 'mime_type' => 'image/jpeg', 'size' => 1.megabyte }).to_json}

結果
imageを実際に使うテストにてエラーが起きる

No such file or directory @ rb_sysopen - /usr/src/app/public/uploads/cache/675ce0d849e8a5f8

ファイルをあげようとしてるんだけど、そんなファイルはないよと言われているように見えます。

shrineを用いた実装において、

image_data → 添付ファイルの全情報がjson形式で保存されるためのDBカラム
image      → 添付ファイルをハンドリングするためのvirtualなattribute

ということは

image_data → upload済みのファイル情報を入れる。
image      → uploadしたいファイル情報を入れる。

最終形では、Shrine.uploaded_fileでファイルが上がっていることにしていたのでimage_dataに入れるのが正解ということでした

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
shibadog39
rubyのエンジニアです。 柴犬が好きです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?