2
1

More than 1 year has passed since last update.

画像投稿機能を追加するgem「CarrierWave」ruby on rails 写真アップロード機能

Last updated at Posted at 2021-08-17

ここでは画像投稿機能を追加する方法について書いています。
Twitter風やInstagram風など、テキストだけではなく画像なども投稿する機能が欲しい場合は「CarrierWave」というgemを追加します。

環境

Windows10
VS code
ruby 2.7
Rails 6.1.4

二つのgemを導入する
ひな形の準備:scaffold
画像投稿機能:CarrierWave

#まずはscaffoldというgemでモデルやコントローラー、ビューを一括で作成

railsではモデルやビューやコントローラなどを作る必要があります。
いちから作っていると面倒なので「scaffold」というgemを使います。
railsアプリケーションの開発をする際には、モデルやコントローラー、ビュー、ルーティングを作成していく必要があります。

##modelsやviews、controllersの確認

image.png
通常、rails newでフォルダを作ると、app直下にmodels、views、controllersなどのファイルが格納されるフォルダが出来上がります。

image.png
appにあるcontrollersの中を見ると、concernsというフォルダとapplication_controller.rbというファイルがあるだけです。
ここへ新たにコントローラーファイルを作るというわけです。

###モデルやviewも確認
image.png
modelフォルダにはapplication_record.rbなどがあり、
viewフォルダにはapplication.html.erbやmailer.html.erbなどがあります。
このようにファイルがありますが、ここへも新しくヴューやモデルファイルも追加します。

railsにはscaffoldというgemを使うことでひな形を一気に作成し、ここでの作業をまとめて行ってくれます。それがscaffoldです。

##scaffoldのインストール
###ターミナルでコマンド入力

rails generate scaffold user name:string age:integer

意味
rails generate scaffold user name:string age:integer
rails generate scaffold モデル名 カラム名:データ型 カラム名:データ型

実行すると以下のような感じでできると思います。

PS C:\aaac> rails generate scaffold user name:string age:integer
      invoke  active_record
      create    db/migrate/20210817130706_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml 
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    resource_route
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      create      test/system/users_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      create      app/views/users/_user.json.jbuilder
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/users.scss
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    resource_route
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      create      test/system/users_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      create      app/views/users/_user.json.jbuilder
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/users.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

##マイグレーションファイルなどが生成
dbフォルダの中にmigrateというフォルダがあります。
この中に、作成した日付がかかれたファイルがあります。
これが先ほど、rails generate scaffold user name:string age:integerとコマンド入力したときに作られたデータベースのカラムとなるファイルです。
image.png

###生成されたマイグレーションファイルの内容

create_table :users do |t|
  t.string :name
  t.integer :age

これでマイグレーションファイルは出来上がりました。
けれどこれだけではデータベースが完成していません。

このあと、rails db:migrateもしくはrake db:migrateというコマンド入力をしてデータベースのテーブルを作成します。
※ railsとrakeの違い、rails5以降はrailsに統一されたのでどっちを使ってもよいと思います。

###rails db:migrateを実行

rails db:migrate

下記のように表示されたら完成です。
image.png

###「schema.rb」「development.sqlite3」ファイルの確認
「schema.rb」「development.sqlite3」というファイルが作成されておりますのでこちらも確認します。
image.png

####「schema.rb」ファイルを確認

ActiveRecord::Schema.define(version: 2021_08_17_130706) do

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.integer "age"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end

image.png

###users_controller.rb
ディレクトリを確認すると下記のようにusers_controller.rbというファイルができています。
image.png

####modelにuser.rbファイルが作られます
image.png

####view>usersにもそれぞれのファイルが作られています。
image.png

##サーバーを起動させviewから確認
できあがったのでサーバーを立てるため下記コマンド入力

rails s

立ち上がったら下記URLへ
http://localhost:3000/users

下記のように画面が出たら成功です。
image.png

###ページが表示されない場合
http://localhost:3000/users
が表示されない場合は、

下記URLにてTOPページを確認してください。
http://localhost:3000/
image.png
TOPページが表示されていればサーバー自体は起動して表示することに関しては問題ありません。

##scaffoldインストール後の使い方
まず、下記のページが表示されています。
image.png

###scaffoldでフロントエンドからユーザのデータを作成
New Userをクリックしてユーザーのデータを作ります。

下記ページが表示されます。
image.png
NameとAgeにそれぞれ名前と年齢を入れます。

image.png

あとはCreate Userをクリックします。
すると以下のように表示されます。
image.png

なおページURLは/user/1となっています。

Edit | Backとありますが、Edit は編集ページに移動します。Backを押すとユーザー一覧ページへ移動します。
同じようにユーザーを登録してみると出来上がりをイメージしやすいかもしれません。
image.png
以上になります。

#【本題】CarrierWaveを導入する(scaffoldに画像投稿機能を追加する)
##gemfileに記述
CarrierWaveを導入するために、gemfileというファイルに下記コマンドを記述する。

gem 'carrierwave'

##carrierwave'を書き込むファイルの場所
image.png

###gemfileを開き、一番下に上記のコードを追加します。

image.png

###CarrierWaveをインストールするためにbundle installを実行
あとはCarrierWaveをインストールするためにbundle installを実行します。

bundle install

インストールされているリストの中で、using CarrierWaveがあれば無事に完了しています。

#CarrierWaveを有効にするために再起動をします
再起動はCtrl+Cで停止にして、rails sで起動させます。
image.png

##アップローダークラスの作成

アップローダークラスのファイルを作成すると、アップロードするときの設定をつくれます。
ファイルのサイズ、拡張子、保存先などを指定する事が出来ます。

画像投稿用としてimgでコマンドを実行します。
img 以外の文字でも大丈夫です。

入力コード例

bundle rails g uploader img

ファイルはapp>uploader>img_uploaderにあります。
image.png

ひとまずアップロードができればよいので、ここで細かい設定などの説明は割愛します。

##投稿画像が保存される場所 画像のアップロード先
img_uploaderには下記のように書かれています。

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

したがって、uploadsのフォルダ内となります。

##投稿する画像の情報をカラムを追加

さきほど、scaffoldでカラムを作りました。
カラムの確認方法は、dbフォルダ内のschema.rbです。
現在は下記のようになっています。※SQLITEの場合

ActiveRecord::Schema.define(version: 2021_08_17_130706) do

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.integer "age"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end

###ここへ画像を保存するカラムを追加します。

rails g migration add_img_to_users img:string

rails g migration Addカラム名Toテーブル名 カラム名:データ型カラム名になる部分は任意。

実行すると、マイグレーションファイルとして追加されます。
image.png

ファイルの中身はこのようになっています。
image.png

###マイグレーションを実行してデータベースのテーブルへ追加

rails db:migrate

追加後、dbフォルダにあるschemaファイルを確認します。
image.png
t.string "img"が追加されています。

##controllerにimgカラムを追加
データベースに保存するためにcontrollerフォルダにあるusers_controllerファイルにカラムを追加します。
image.png

ファイルの中に下記の記述があります。
image.png

ageのあとに, :imgを追加します。

def user_params
  params.require(:user).permit(:name, :age, :img) 
end

##投稿画像の設定をするアップローダークラスとカラム名imgを紐付ける
modelsフォルダにuser.rbというファイルがあるのでそこを開きます。
image.png

ファイル内は何も記述されていません。
image.png

ここへ下記コードを書き込みます。

class User < ActiveRecord
  mount_uploader :img, ImgUploader
end

画像投稿時に、アップローダークラスに書かれている設定が反映されます。つまり画像のサイズや画像の投稿フォルダや拡張子などです。

##注意 user.rbファイル class User < ActiveRecord
class User < ActiveRecordの部分で下記のようにするとエラーになります。

class User < ActiveRecord::Base

Baseを記述したららNameerrorが表示されました
image.png

#viewsの設定 投稿フォームに画像が投稿できるようにする
次はフロントエンド側の設定です。
下記のように、まだ画像を投稿するフォームがありません。
画像を投稿するようにします。
image.png

まずusersフォルダへ移動して_form.html.erbを開きます。
image.png

名前や年齢の下に入れたいので下記コードを貼ります。

<div class="field">
  <%= form.label :img %>
  <%= form.file_field :img %>
</div>

ページ内の下記へ貼ります。
image.png

localhost:3000/users/newを表示
ファイルが投稿できるようになっています
image.png

###表示させる部分show.html.erbにコード追記
下記のコードをusers>show.html.erbのファイルのageの下に貼り付けます。

<% if @user.img? %>  
  <p>
    <strong>post img:</strong>
    <%= image_tag @user.img.url %>
  </p>
<% end %>

貼り付ける場所
image.png

##動作確認のためユーザ登録を表示させる

適当に名前や年齢をいれ、画像も入れます

image.png

このように画像が投稿されます
image.png

ユーザー一覧ではこのように表示されます
image.png

以上になります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1