【Rails】 応募機能の実装

### 前提
* `applicantモデル`(applicantsテーブル)を作成していること
    * カラムは`user_id:int`、`job_id:int`
* `applicantsコントローラー`を作成していること

```ruby:config/routes.rb
Rails.application.routes.draw do
  resources :jobs, only: [:new, :create, :edit, :index, :show, :destroy] do
    resource :applicants, only: [:create, :destroy] # 追加するルーティング
  end


  root "home#top"
  resources :users, only: [:new, :create, :edit, :destroy, :update]
  # post "users/create" => "users#create", as: "create_users"
  # get "users/:id/edit" => "users#edit", as:"edit_users"
  # post "users/:id/update" => "users#update", as:"update_users"
  get "signup", to: "users#new", as: "new_users"
  resources :guest_sessions, only: [:create]
  # post "guest_login", to: "guest_sessions#guest_login"
  # get "guest_login", to: "guest_sessions#guest_login"
  post "logout" => "sessions#destroy"
  # get "logout" => "sessions#destroy"
  get "login", to: "sessions#new", as: "new_sessions"
  post  "login", to: "sessions#create", as: "create_sessions"
  delete "logout", to: "sessions#destroy", as: "destroy_sessions"
  # get "users/:id/destroy", to: "users#destroy"
  # delete "users/:id/destroy", to: "users#destroy", as: "destroy_users"
end
```

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_current_user

  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end
```

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 100 }, uniqueness: true
  has_many :applicants, dependent: :destroy
end
```

```ruby:app/models/job.rb
class Job < ApplicationRecord
  validates :salary, presence: true, length: { maximum: 5 }
  has_many :applicants, dependent: :destroy
  has_many :users, through: :applicants
end
```

```ruby:app/models/applicant.rb
class Applicant < ApplicationRecord
  belongs_to :user
  belongs_to :job
  validates :user_id, presence: true, uniqueness: { scope: :job_id}
  validates :job_id, presence: true
end
```

```ruby:app/controllers/applicants_controller.rb
class ApplicantsController < ApplicationController

  def create
    @applicant = @current_user.applicants.new(job_id: params[:job_id])
    if @applicant.save
      flash[:success] = "応募しました"
    end
  end

  def destroy
    @applicant = Applicant.find_by(user_id: @current_user.id, job_id: params[:job_id])
    if @applicant.destroy
      flash[:success] = "応募解除しました"
    end
  end

end
```

画面はこんな感じです。一番下の「応募ボタン」を押すと応募状態になります。現在テストユーザー1(id:2)でid２のお仕事を表示しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207701/0119c063-d110-1b73-92d7-3a61349c26e3.png)

押してページを手動で更新させると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207701/8db7cfb3-30ac-e7f3-652e-65448ea79e02.png)

「応募解除ボタン」に変わりました。MySQLで`applicantsテーブル`を見てみると
```
mysql> select * from  applicants;
+----+---------+--------+----------------------------+----------------------------+
| id | user_id | job_id | created_at                 | updated_at                 |
+----+---------+--------+----------------------------+----------------------------+
|  5 |       2 |      2 | 2023-05-11 00:34:59.486131 | 2023-05-11 00:34:59.486131 |
+----+---------+--------+----------------------------+----------------------------+
1 row in set (0.00 sec)
```
きちんと応募した情報が保存されていることがわかりました(id2のユーザーがid2のお仕事に応募した)

この状態で「応募解除ボタン」を押して手動でページを更新すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207701/1fe79084-7014-00a9-9fbe-be7595b9c4fe.png)

「応募ボタン」に戻りました。MySQLで見てみると
```
mysql> select * from  applicants;
Empty set (0.00 sec)
```
きちんとデータが消えていることがわかりました。

### 参考
* [【Rails】いいね機能の実装手順 | たみずブログ](https://tamiz-blog.com/programming/rails20190706/)