【Rails】ファイルをデータベースに保存する方法
ファイルを保存する方法はRailsチュートリアルとかでは、CarrierWave
というgemを使う。
だがちょっとしたアプリとか作りたい時には、DBに保存した方が都合がいい時もあるはず。
gemを使う方法は別の機会でまとめるとして、今日はDBに保存する方法を。
モデルを作る
$ rails g model Image name:string picture:binary invoke active_record create db/migrate/20171215092903_create_images.rb create app/models/image.rb
# migrate class CreateImages < ActiveRecord::Migration[5.0] def change create_table :images do |t| t.string :name t.binary :picture t.timestamps end end end
$ rails db:migrate == 20171215092903 CreateImages: migrating ===================================== -- create_table(:images) -> 0.3369s == 20171215092903 CreateImages: migrated (0.3370s) ============================
コントラーラーを作る
$ rails g controller Images Running via Spring preloader in process 7555 create app/controllers/images_controller.rb invoke erb create app/views/images invoke helper create app/helpers/images_helper.rb invoke assets invoke coffee create app/assets/javascripts/images.coffee invoke scss create app/assets/stylesheets/images.scss
# images_controller.rb class ImagesController < ApplicationController def new @image = Image.new @image.name = "hogehoge" end def create @image = Image.new(image_paprams) @image.name = params[:image][:picture].original_filename @image.picture = params[:image][:picture].read if @image.save redirect_to root_path else render 'new' end end private def image_paprams params.require(:image).permit(:name, :picture) end end
ビューを作る
# new.html.erb <%= form_for(@image) do |f| %> <div class="form-group"> <%= @image.name %> <%= f.file_field :picture %> <%= f.submit "画像を投稿する" %> </div> <% end %>
↓htmlに変換されると...
<form class="new_image" id="new_image" enctype="multipart/form-data" action="/images" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="ZgO8WthU8KtI/rspO/oVgHavcwUUVQl1jDwm0DQAsZXwCHYLO02KUqcX+Kt54gKlUlQP4sqDe3NUltVWjtZQDw=="> <div class="form-group"> hogehoge <input type="file" name="image[picture]" id="image_picture"> <input type="submit" name="commit" value="画像を投稿する" data-disable-with="画像を投稿する" disabled=""> </div> </form>
まとめ
こんな感じでしょうか。 とりあえず言いたいことは、
binary
型のカラムをモデルに用意します。form_for
でf.file_field
を使います。params[:image][:picture].read
で画像データが保存できる
form_for
がよしなにやってくれるのは分かるのだけど、いまいち理解が浅いので色々動かしてみて勉強しよう。
で、実際に登録された画像データはこんな感じです。
$ rails c > Image.all Image Load (1.6ms) SELECT "images".* FROM "images" => #<ActiveRecord::Relation [#<Image id: 1, name: "17704-koala-bear-pv.jpg", picture: "\xFF\xD8\xFF\xE0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xFF\xDB\x00C\x00\n\a\a\b\a\x06\n\b\b\b\v\n\n\v\x0E\x18\x10\x0E\r\r\x0E\x1D\x15\x16\x11...", created_at: "2017-12-15 09:52:29", updated_at: "2017-12-15 09:52:29">]>