refileの使い方徹底解説②

前回は基本的なrefileの使い方を見ていきました。

今回は画像がどこに保存されるのかを調べていきます。

まずはviewから画像を保存できるようにします。

/books/new にアクセスします。

スクリーンショット 2020-07-31 17.50.08

ここからまずタイトルと画像を保存できるようにします。

# _form.html.erb
<%= form_with(model: book, local: true) do |form| %>
 # 省略
 
 <%= form.text_field :title %>
 <%= form.attachment_field :main_image %>

 <div class="actions">
   <%= form.submit %>
 </div>
<% end %>

refileでは画像をアップロードするために attachment_field というhelperが提供されているのでこれを使用します。

こんな感じになります。

スクリーンショット 2020-07-31 17.53.23

適当に値を入力してみます。

スクリーンショット 2020-07-31 17.54.30

保存します。

スクリーンショット 2020-07-31 17.55.10

保存できたようです。一応、ログを確認してみます。

Started POST "/books" for ::1 at 2020-07-31 17:55:04 +0900
Processing by BooksController#create as HTML
 Parameters: {"utf8"=>"✓", "authenticity_token"=>"I+UxMoDJEwSHiEBdJ3l/YgYjQtMlCyXRI0GpTYoIM9DK5CCEl+dhHv/RG958N3xT4EHiQcK08qDYW9MpYLx+Ig==", "book"=>{"title"=>"テスト1", "main_image"=>#<ActionDispatch::Http::UploadedFile:0x00007f977a1cf868 @tempfile=#<Tempfile:/var/folders/qz/rvvc7fwn75x4dyv2tk72q2600000gn/T/RackMultipart20200731-27990-hte399.png>, @original_filename="rails_logo.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"book[main_image]\"; filename=\"rails_logo.png\"\r\nContent-Type: image/png\r\n">}, "commit"=>"Create Book"}
  (0.1ms)  begin transaction
 ↳ app/controllers/books_controller.rb:30
 Book Create (2.2ms)  INSERT INTO "books" ("title", "main_image_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["title", "テスト1"], ["main_image_id", "c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb"], ["created_at", "2020-07-31 08:55:04.808779"], ["updated_at", "2020-07-31 08:55:04.808779"]]
 ↳ app/controllers/books_controller.rb:30
  (0.8ms)  commit transaction
 ↳ app/controllers/books_controller.rb:30
Redirected to http://localhost:3000/books/2
Completed 302 Found in 13ms (ActiveRecord: 3.1ms)

ログをみても保存処理が成功していることがわかりました。

今度はviewに保存した画像を表示してみます。

# show.html.erb
<p id="notice"><%= notice %></p>

<%= attachment_image_tag(@book, :main_image, :fill, 300, 300) %>

<%= link_to 'Edit', edit_book_path(@book) %> |
<%= link_to 'Back', books_path %>

画像を表示するには attachment_image_tag を使います。bookのshowページにアクセスしてみます。

スクリーンショット 2020-07-31 18.02.33

エラーが表示されました。エラー文を読んでみると

Refile.secret_key was not set.
Please add the following to your Refile configuration and restart your application:

となっているので表示されている secret_key を設定します。

config/initializers/application_controller_renderer.rb にエラーメッセージに表示されている secret_key を 記述します。

# application_controller_renderer.rb
# xxxはエラーメッセージに表示されているsecret_keyを記述する
Refile.secret_key = 'xxx'

そしてrailsを再起動します。

~/w/r/refile_app ❯❯❯ rails s

再度bookのshowページにアクセスしてみると

スクリーンショット 2020-07-31 18.11.10

画像が表示されていることを確認できました。

今度はこの画像はどこに保存されているのか確認してみます。

rails cでbooksテーブルのデータを見てみます。

~/w/r/refile_app ❯❯❯ rails c                                                              master ◼
BRunning via Spring preloader in process 32676
Loading development environment (Rails 5.2.4.3)
irb(main):001:0> Book.first
 Book Load (0.4ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Book id: 1, title: nil, main_image_id: "1bae063ba8442393dd62a7fdac3d4a6a8d82ab6d76cd83d8bc...", created_at: "2020-07-31 08:26:35", updated_at: "2020-07-31 08:26:35">

画像を保存しているのは main_image_id というカラムなのでこのメソッドを呼び出してみます。

irb(main):002:0> Book.last.main_image_id
 Book Load (0.2ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> "c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb"

こいつの正体は何なのかを調べてみます。まずはこのデータがどのclassに属しているのかを確認してみます。

irb(main):003:0> Book.last.main_image_id.class
 Book Load (0.1ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> String

booksテーブルのmain_image_idカラムはstring型に設定したので当たり前だがstring class と表示されます。

これだけを見てみてもよくわからないのでもう一度showページを開いてみます。

chromeの検証モードで画像を確認してみます。

スクリーンショット 2020-07-31 18.19.56

表示されるHTMLのタグのsrcに 

/attachments/8d205ec96253ec2bbf4324caea1a41dd02268d07/store/fill/300/300/c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb/main_image

と表示されていました。どうやらbooksテーブルのmain_image_idに保存されている値は c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb の部分を表しているようです。

プログラムの動きやデータのみではよくわからなかったのでGem refileのGithubを確認してみます。

By default files will be uploaded to ./tmp/uploads/store.

と書かれており、どうやら tmp ディレクトリ以下に実際のファイルがアップロードされているとのことです。確認してみます。

~/w/r/refile_app ❯❯❯ ls tmp/uploads/store                                                    master ◼
c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb
irb(main):002:0> Book.last.main_image_id
 Book Load (0.2ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> "c701185ec9d93759c5c64c93078ca7343f4f501422420d3ddec64b1583eb"

確かにrails cで確認した最後に登録した画像と同じidのファイルが tmp/uploads/store 以下に保存されていました。

どうやら main_image_id カラムに保存するデータは、ファイルにランダムな値を割り振ってidとして管理し、そのidのファイルがtmp/uploads/store 以下のどのファイルかを判定するための識別子のようでした。

これで画像を保存する一連の流れ、どこに保存されるのかということが理解できました。

次回は複数枚画像を保存する方法を見ていきます。

この記事が気に入ったらサポートをしてみませんか?