チーム開発のフリマアプリのitemsコントローラーを説明できるか？

# この記事を書いた理由
私は現在あるプログラミングスクールに通っており、そこでチーム開発を行っています。
チーム開発ではフリマアプリを制作しています。  
今回私は出品機能実装の担当になったのですが、ペアを組んでいる方が優秀すぎて、サーバーサイドをほぼほぼ１人で実装してしまいました。
チームとして進んでいるのはありがたいのですが、自分自身は成長していないので、焦りを感じています。  
そこで、自分にできるアウトプットとして、「実装をどこまで説明できるか？」Qiitaに書くことにしました。
「説明できる＝再現性が高い」ということになると思ったのです。

# 前提
私たちのチームでは、商品出品機能は`items_controller.rb`で行うことにしました。
私の理解が危ういのがcreateメソッドなので、他のindexメソッドやnewメソッドなどの説明は省略しています。

# ソースコード
```ruby:items_controller.rb
class ItemsController < ApplicationController
  before_action :move_to_index, except: [:index, :show]

  def create
    @item = Item.new(item_params)
    if @item.save
      selling_status = SellingStatus.new(item_id: @item.id, seller_id: params[:user_id], status: "出品中")
      seller = Seller.new(item_id: @item.id, user_id: params[:user_id])
      if selling_status.save && seller.save
        redirect_to item_path (@item.id)
      else
        flash.now[:alert] = 'エラーが発生しました。'
        render :new
      end
    else
      flash.now[:alert] = '入力されていない項目があります。'
      render :new
    end

  private
  def item_params
    params.require(:item).permit(:name, :description, :price, :condition, :brand_id, :category_id, :shipping_id, images_attributes: [:image], shipping_attributes: [:shipping_day, :shipping_fee, :shippingway_id, :shippingarea_id])
  end

  def move_to_index
    redirect_to action: :index unless user_signed_in?
  end
end
```

## @item = Item.new(item_params)の説明
```ruby
@item = Item.new(item_params)
```
右辺から説明すると、`Items`これはitemモデルですね。
`.new`これはitemモデルに「新しい情報を作って」と言っているんですね。
`items_params`これは引数ですね。  
下の方を見てもらうと、このような記述があります。

```ruby
private
  def item_params
    params.require(:item).permit(:name, :description, :price, :condition, :brand_id, :category_id, :shipping_id, images_attributes: [:image], shipping_attributes: [:shipping_day, :shipping_fee, :shippingway_id, :shippingarea_id])
  end
```
ストロングパラメータ`items_params`の中には、出品フォームで入力した 出品する商品の情報が入っています。具体的には、商品名・商品説明・価格・商品の状態・ブランドid・カテゴリーid・画像などです。

requireの後ろの`:item` これはitemモデルのことですね。
`:name``:description``:price``:condition`などはitemテーブルのカラムを指しています。
すなわち、商品名・商品の説明・商品の価格・商品の状態など、items#new(itemsコントローラーのnewアクション)で送られてきた情報を運ぶための段ボール箱が`item_params`です。  
`item_params`に入った情報（出品される商品の情報）を引数として、Itemモデルに新しいデータを作らせて、それを左辺の`@item`に代入するというわけですね。

以上のことから、`@item`には、出品画面のフォーム（itemsコントローラーのnewアクション）で入力された情報が入っていることになりますね。
## if @item.saveの説明
```ruby
if @item.save
```
ここから苦手な条件分岐に入っていきます。
`@item`これはさっき説明しましたが、出品画面で入力された情報が入っているんでしたね。
`.save`これは「ゲームをセーブする」とかよく言いますが、あれと同じで、「保存して」という意味ですね。
なので、`@item.save`の意味は、「フォームで送られてきた出品情報を保存する」ですね。
それに`if`がついているので、「フォームで送られてきた出品情報を保存できた場合」となります。

## selling_status = SellingStatus.new(item_id: @item.id, seller_id: params[:user_id], status: "出品中")の説明
```ruby:items_controller.rb
selling_status = SellingStatus.new(item_id: @item.id, seller_id: params[:user_id], status: "出品中")
```
これも右辺から見ていきましょう。
`SellingStatus`これはSellingStatusモデルのことです。これは、商品の出品状態を管理するためのモデルです。

出品状態は２つあり、「出品中」か「売却済み」です。
「売却済み」の商品を購入できないようにする必要があったため、商品をこれら２つの商品状態で分けて保存することにしました。

SellingStatusモデルのカラムは、`id`, `status`, `seller_id`, `item_id`の4つです。
idはデフォルトで設定される主キーでなので説明は省きます。

`status`から説明しましょう。これは先ほど説明した通り「出品中」か「売却済み」の2通りです。
`seller_id`と`item_id`は、「どの出品者のどの商品か」がわかるようにするために設定しました。

`seller_id`がないと、「この商品は誰が出品したの？」となってしまい、出品者がわからなくて購入できない事態が生じてしまいます。

ここで改めてcontrollerの記述を見ると、SellingStatusモデルに新しくデータを作るように言っていますね。`.new`とあるので。

```ruby:items_controller.rb
selling_status = SellingStatus.new(item_id: @item.id, seller_id: params[:user_id], status: "出品中")
```
その後ろの（　）は先ほども説明しましたが、引数ですね。
SellingStatusモデルには、item_idカラム、seller_idカラム、statusカラムの3つのカラムがあるので、それら3つの情報を引数で渡しています。

つまり、左辺の`selling_status`には、「どの商品か」「どの出品者か」「出品中or売却済み」という３つの情報が代入されることになります。

# 終わりに
やや中途半端ですが、今回はここまでにします。
かなりまどろっこしい説明になりましたが、自分としては理解が曖昧な点に気づきクリアにすることができたので、良い学びの機会になりました。

説明の手段としては、今回のように「文章で伝える」他に、「スライドで伝える」「動画で伝える」「口頭で伝える」といった方法もあるので、今後はそういった他の手段での説明にもチャレンジしていきたいと思います。