ℙ𝕚𝕜𝕠𝔹𝕝𝕠𝕘 | プログラミングについて知ろう!

【HTML/CSS/JavaScript/jQuery/Ruby/Swift/MySQL/AWS】 プログラミングを 「今始めたばかりの方」や 「これから始めるか悩んでいる方」、 好きか嫌いかも分からない、 できるかどうかも分からない、 向いてるか向いてないかも分からない、 そんな思いを抱えた方へ届くような ブログを執筆していきます。

スポンサーリンク

Rails 画像投稿のやり方(carrierwaveとmini_magick)

スポンサーリンク

こんにちは!

 

今回は、プログラミングスキル学習のために

画像投稿練習用アプリを作りました。

 

内容は、

・商品モデルと商品の画像モデルを作成し、1つの投稿フォームで記事とそれに紐づく複数の画像を投稿できる。です。

 

バージョンの確認。

上のコマンドを入力すると、下にバージョンが出ます。

1
2
ruby -v
Ruby 2.5.1

 

1
2
rails -v
Rails 5.2.3

 

早速始めていきます。

1
2
3
$ rails new  mini_listing -d mysql
$ cd mini_listing
$ bin/rails db:create

※bin/rails db:createの中にある「bin」とは、

  binaryの略でbinary形式で作るというコマンドになってます。

 

データベースが作成できたら、次はコントローラーです。

1
$ bin/rails g controller products
コントローラー ができたら中身を書いていきます。
 
products_controller.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class ProductsController < ApplicationController
  def index
    @products = Product.includes(:images).order('created_at DESC')
  end

  def new
  end

  def create
  end

  def edit
  end

  def update
  end

  def destroy
  end
end

 次にルートの書いていきます。

①始めは、「ようこそRailsへ」って画面になるので

topのルートを修正。

 

②さらに、今回の出品機能(product)は、top表示と

投稿(new、create)、編集(edit、update)、削除(destroy)、、、つまり詳細(show)以外を使用するので

以下のように記述します。

 

routes.rb
1
2
root 'products#index'
resources :products, except: :show

1行目は、topは「ここですよ」という記述。

2行目は、 出品(product)では、詳細(show)以外を使う。

という記述。

※この「以外」と表す記述が「except」です。

 

次にproductで必要なviewファイルを作成。

1
2
3
4
5
6
products
- index.html.erb
- new.html.erb
- edit.html.erb
- _form.html.erb
- _product.html.erb

 ※このhtml.erbは、

Rubyが組み込まれたhtmlのようなファイル」という意味。

Railsでviewを作る時は、このようにRubyの記述で作ります。

 

では、各viewファイルを書いていきます。

まず最低限の見た目を作るため、以下記述。

index.html.erb
1
2
3
4
<%= link_to '出品', new_product_path %><br>
<div class="contents">
  <%= render @products %>
</div>
_product.html.erb
1
2
3
4
5
6
7
<div class="content">
  <p><%= product.name %></p>
  <p><%= product.price %></p>
  <% product.images.each do |image| %>
    <%= image_tag image.src.url %>
  <% end %>
</div>

render = @products によって、「_product.html.erb」の中身を読み込み、1ページを出力してます。 

※「_(アンダースコア)」を始めにつける事で対象のviewファイルをテンプレートにすることができます。

またテンプレート化させることで記述をすっきりさせるだけでなく、修正など管理もしやすくなります。

 

 

次に以下2つのファイル内に追記。

new.html.erb、edit.html.erb
1
<%= render partial: 'form' %>

 

 

 ここまではview(見た目)ができました。

次はmodel(中身のやりとり)について進めていきます。

1
2
$ bin/rails g model product
$ bin/rails g model image

①出品情報(product)のモデル作成

②画像情報(image)のモデル作成

これで2つのモデルができました。

 

また中身の修正とモデル作成した時は、必ず

migrate実行(すぐ気づくけど、よく忘れる)

XXXXXXXXXX_create_products.rb
1
2
t.string :name
t.integer :price
XXXXXXXXX_create_images.rb
1
2
t.string :src
t.references :product, foreign_key: true

 できたら

rails db:migrateコマンドを実行。

 

ちゃんとできたか不安な時、

ターミナルにできたかエラーか書いているが!

僕のように英語得意じゃない、もしくはターミナルに書いている文章が呪文のように見える方は、

 

rails db:migrate:statusとコマンドを入れると

対象のmigrationファイルがUP(できてる)か

DOWN(できてない)か分かります。

 

またmigrateしたけど、記述間違えた!というときには

rails db:rollbackコマンドを実行。

 

すると1つ前の物がDOWNに戻ります。

 

※このDOWN状態の時のみ修正ができるので、間違えて直したい時はこの手順で進めます。

 

修正が終わったら、再度

rails db:migrateコマンドを実行。

 

※ファイルがUP状態でないとエラー出ます。

 

f:id:kakikazu:20200207153312j:plain

 

 

 次は、必要なgem(ジェム)を入れます。

 

gemとは、

ruby(ルビー)という言語の中にインストールする、gem(宝石)という便利ツールのことです。

 

今回入れる2種類のgemだけでなく、とてもたくさんの便利なgemがあります。

今後もブログ更新しながらgemの紹介もしていきますのでぜひ見てみてください。

 

では、手順です。

やり方は簡単! 対象の場所に書いて、インストールするだけ!

以下、ファイルの最下部に記述。

 

Gemfile

1
2
gem 'carrierwave'
gem 'mini_magick'

できましたら、あとはターミナルで

bundle installとコマンドを打つだけ!(bundleだけでも行ける) 

これでgemがインストールできました。

 

 続いて、今回入れたgemを使うための設定をしていきます。

 

まずは

$ rails g uploader image

 uploaderを作成します。

 

できたファイル等を修正していきます。

 

image_uploader.rb
1
2
3
include CarrierWave::MiniMagick  // この記述を探し、コメントアウトを外す

process resize_to_fit: [100, 100]  // この記述は追記

モデルファイルもそれぞれが正しく紐づくように

追記していきます。

 

product.rb
1
has_many :images
image.rb
1
2
mount_uploader :src, ImageUploader
belongs_to :product

 

※has_manyは、productからimageをみた時、

 ひとつ出品(product)に対して、複数の画像(image)があるのでこの記述をします。 対象が複数なので英語の複数形でimagesと記述します。

 

※対してbelongs_toは、imageからproductをみた時、

 たくさんの画像をひとつの出品に紐付ける仕様にするので、この場合はこの記述を使います。 相手は常に単数なのでここでは複数形にあたる「s」は付けません。

 

初めはこの使い分けが分からなかったので、復習のため書きました。

 

 

 

 

 

 

 

ここから画像投稿機能の本格的なところを実装していきます。

※今回は、次回に続く複数枚画像を投稿したり、プレビューしたり機能追加予定のため、通常と違う記述をしていきます。

 

そこだけ注意しながらみていただけたらと思います。

 

では最初に、使うヘルパーメソッド

fields_for

複数の別のリソースを同時に保存する際に利用。

accepts_nested_attributes_for

fields_forとセットで使用。 親モデルに書くことで

モデルの親子関係を作ります。

 allow_destroy: true

 accepts_nested_attributes_forメソッドのオプション。 親のレコードが削除されると、紐づいた子のレコードも削除することができます。

 

 

 

上記をもとに記述していきます。

product.rb
1
accepts_nested_attributes_for :images, allow_destroy: true
 
投稿(new)機能を付けていきます。
products_controller.rb
1
2
3
4
def new
  @product = Product.new
  @product.images.new
end

newとeditで読み込むテンプレートの中身を記述。

_form.html.erb
1
2
3
4
5
6
7
8
<%= form_for @product do |f| %>
  商品名<%= f.text_field :name %><br>
  価格<%= f.number_field :price %><br>
  <%= f.fields_for :images do |i| %>
    <%= i.file_field :src %><br>
  <% end %>
  <%= f.submit %>
<% end %>

 ここで使うfields_forによって親(product)に紐づく子(image)が投稿の数だけ生成されていく形ができます。

 

 最後に投稿までの動きをコントローラーに追記すれば、完成です。

products_controller.rb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def create
  @product = Product.new(product_params)
  if @product.save
    redirect_to root_path
  else
    render :new
  end
end

〜〜〜 中略 〜〜〜

private def product_params params.require(:product).permit(:name, :price, images_attributes: [:src]) end

 fields_forを利用して作成されたフォームから来る値は、○○s_attributes: [:××]という形でparamsに入ります。○○は関連付く側のモデルの名前、××にはフォームに対応するカラムの名前が入ります。

 

 

最後までお付き合いいただきありがとうございます!

次回は、ここをベースに複数枚画像投稿機能の実装につなげていきますので次回もよろしくお願いします。

 

 

 

 

スポンサーリンク