class_nameオプションを使ったミニアプリ

# はじめに
・前回の記事はこちら↓
商品を売ったり買ったりする場合にclass_nameを使ってみた
https://qiita.com/fishmans0120/items/5b40fb2a057e4d722a67
・備忘録として書いています。
・間違いなどあればご指摘いただけますと幸いです。

# 今回の前提条件とゴールについて
・usersテーブルがある
・itemsテーブルがある
・商品を売ったり買ったりすると仮定する
・中間テーブルはつくらない
・seller_idにログインユーザーのidが表示される←ここをゴールにします

# さっそくミニアプリを作ってみます

```terminal:ターミナル
$ rails _6.0.0_ new class_name_app -d mysql
```
railsのバージョンを6.0.0に指定して、
class_name_appという名前のアプリケーションを、
データベースMySQLで、
生成します。

```terminal:ターミナル
$ cd class_name_app/
```
ディレクトリを移動しました。
ユーザーを生成するためと、haml記法を使うためにgemをインストールします。

```ruby:Gemfile
gem `devise`
gem `haml-rails`
```
```terminal:ターミナル
$ bundle install
```
これでdeviseとhaml-railsが使えるようになりました。
データの保存形式を変更します。

```config/database.yml
# encoding: utf8mb4
encoding: utf8
```
データベースを生成しましょう。

```terminal:ターミナル
$ rails db:create
```
ではitemsテーブルを作っていきます。

```terminal:ターミナル
$ rails g model item
```
```ruby:db/migrate/20200818025529_create_items.rb
class CreateItems < ActiveRecord::Migration[6.0]
  def change
    create_table :items do |t|
      # 商品名を入力するためにstring型でnameカラムを作成します
      t.string :name

      t.timestamps
    end
  end
end
```
```terminal:ターミナル
$ rails db:migrate
```
これでitemsテーブルができました。
nameカラムがstring型で追加されています。

次にusersテーブルを作ります。

```terminal:ターミナル
$ rails g devise:install
$ rails g devise user
$ rails db:migrate
$ rails haml:erb2haml
```
この順で入力してください。
usersテーブルができあがります。
サインアップ、ログイン、ログアウトもできるようになりました。
最後のコマンドは現在erb記法で記述されているファイルをhaml記法に変換するコマンドです。途中で入力を求められたら`y`を入力してください。

`なお、今回はusersテーブルにユーザー名を表示させるnameカラムを作っていません。
必要であれば追加してください。`

itemsコントローラーを生成して、ルーティングも設定します。

```ruby:app/controllers/items_controller.rb
class ItemsController < ApplicationController
  def new
    @item = Item.new
  end
  def create
    @item = Item.new(item_params)
    if @item.save
      redirect_to new_item_path
    else
      render 'new'
    end
  end

  private
  def item_params
    params.require(:item).permit(:name).merge(seller_id: current_user.id)
  end
end
```

```ruby:confin/routes.rb
Rails.application.routes.draw do
  devise_for :users
  resources :items
  root 'items#new'
end
```
ビューファイルはこのようにします。

```ruby:app/views/new.html.haml
%h1 Items#new
%p Find me in app/views/items/new.html.haml

.logout
  = link_to "ログアウト", destroy_user_session_path, method: :delete
.login
  = link_to "ログイン", new_user_session_path, class: "post"
.signup
  = link_to "新規登録", new_user_registration_path, class: "post"
.form
  = form_with model: @item, local: true do |f|
    = f.text_field :name
    = f.submit "送信"
```
ざっくり言うと、
・newアクションで新規入力し、createアクションでデータを新規登録する
・ちゃんとセーブできたらnew画面へリダイレクト、セーブできなかったらnew画面へデータそのままで戻る
・localhost:3000へアクセスしたら自動的にnew画面になりますよ
・ログアウトボタンを押すとログインしてない状態になります
・ログインボタンを押すとログイン画面に遷移します
・新規登録ボタンを押すとサインアップ画面に遷移します
・商品名を入力して送信ボタンを押すとテーブルにデータが保存されます

こんな感じです。でもまだやることが残っています。
モデルファイルに追記しましょう。

```ruby:models/item.rb
class Item < ApplicationRecord
  belongs_to :buyer, class_name: "User", foreign_key: "buyer_id", optional: true
  belongs_to :seller, class_name: "User", foreign_key: "seller_id"
end
```
### ここ大事！！！
Rails 5.1からの変更点として、belongs_toを指定した時、自動的にrequired: trueオプションが追加されpresenseのバリデーションが走るようになったようです（https://github.com/rails/rails/issues/34454 )。
そのため、今回のケースでは`buyer_idのほうにoptional: trueをかけてpresenseのバリデーションを追加しないように指定する`ことが必要です。
こうしないとユーザー新規登録時と購入時にbuyerを入力してくださいと言われちゃいます。

```ruby:models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :validatable
  has_many :bought_items, class_name: 'Item', foreign_key: 'buyer_id'
  has_many :sold_items, class_name: 'Item', foreign_key: 'seller_id'
end
```
class_nameの記述をしました。
仕組みについては[前回の記事](https://qiita.com/fishmans0120/items/5b40fb2a057e4d722a67)を見てください。

itemsテーブルにseller_idカラムとbuyer_idカラムをinteger型で追加します。

```terminal:ターミナル
$ rails g migration AddColumnToItems
```

```ruby:db/migrate/20200818033036_add_column_to_items.rb
class AddColumnToItems < ActiveRecord::Migration[6.0]
  def change
    add_column :items, :seller_id, :integer
    add_column :items, :buyer_id, :integer
  end
end
```

```terminal:ターミナル
$ rails db:migrate
```
これでカラムが追加されました。
ではデータベースを起動してみましょう。

```terminal:ターミナル
$ rails s
```
ブラウザで`localhost:3000`にアクセスしてください。
![スクリーンショット 2020-08-19 9.47.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630925/3777c083-b091-dd0d-b2d0-703d39e00510.png)
こんな画面になっているかと思います。
まずは新規登録でユーザーを作成してください。
その後、入力フィールドに商品名を入力して送信を押すと、テーブルにデータが保存されるはずです。
sequelProなどでテーブルの中身を見ると、seller_idのところにログインしているユーザーのidが入っていると思います。（僕は`id:2`のユーザーでログインしていたので`seller_id:2`になっています）
![スクリーンショット 2020-08-19 9.55.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630925/cb71ab98-54e8-82dc-e1c5-d3b762343d7a.png)


# おわりに
ここまでの流れで問題がなければ、開発環境で実装できるのではないかと思います。

備忘録として書いていますが、以下少しだけ。
僕は新しいことを実装する前には簡単なミニアプリを作ってから実装するようにしているのですが、頭の整理にもなってていいなと思っています。
まだまだ初学者の域を抜けませんが、他の方の助けになりましたら幸いです。
ありがとうございました。