【Rails】カテゴリー機能

#はじめに
レシピ投稿サイトを作成し、レシピに紐づくカテゴリー機能を実装します。
gemのancestryは使っていません。
RecipeモデルとUserモデルが紐づいており、1ユーザーが複数投稿できる仕様です。その辺りは割愛させて頂きます。
投稿(Recipe)とカテゴリー(Category)のモデル、コントローラーは実装済みで進めさせて頂き、今回は投稿とカテゴリーの紐付けについての内容に重点を置いてQiita投稿させて頂きます。

#完成イメージ
入力フォーム
![スクリーンショット 2021-02-20 20.38.00 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973512/39754dce-e8d4-b9cc-66e4-172231b53902.png)
レシピ一覧
![スクリーンショット 2021-02-20 20.38.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/973512/3dfb5825-3c97-9b6c-6db5-2b4c1e396ee7.png)

#中間テーブルの作成
recipe_category_relationsテーブルを中間テーブルとします。

```
$ rails g model Recipe_category_relation recipe_id:integer category_id:integer
```

```ruby:db/schema.rb 
 create_table "categories", force: :cascade do |t|
    t.string "category_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "recipe_category_relations", force: :cascade do |t|
    t.integer "recipe_id"
    t.integer "category_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "recipes", force: :cascade do |t|
    t.string "recipe_title"
    t.text "recipe_body"
    t.string "image_id"
    t.integer "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "recipe_food"
  end

```

#投稿のモデル、中間テーブル、カテゴリーテーブルの関連付け

```ruby:app/models/recipe.rb
class Recipe < ApplicationRecord
  has_many :recipe_category_relations
  has_many :categories, through: :recipe_category_relations
end
```

```ruby:app/models/recipe_category_relation.rb
class Recipe_category_relation < ApplicationRecord
  belongs_to :recipe
  belongs_to :category
end
```

```ruby:app/models/category.rb
class Category < ApplicationRecord
  has_many :recipe_category_relations
  has_many :recipes, through: :recipe_category_relations
end
```

through: :recipe_category_relationsの記述で、中間テーブルrecipe_category_relationを経由してrecipeとcategoryが関連付けることができます。

#viewに表示
```erb:app/views/recipes/new.html.erb
<h1>レシピ投稿</h1><br>
 <%= form_with model:@recipe, url: recipes_path , local:true do |f| %>
   <%= f.attachment_field :image %>
   <%= f.label :title, '料理名'%>
   <%= f.text_field :recipe_title, class:"form-control", placeholder:"料理名" %>
   <%= f.label :category, 'カテゴリ' %>
   <%= f.collection_check_boxes(:category_ids, Category.all, :id, :category_name) do |category| %>
     <%= category.label do %>
       <%= category.check_box %>
       <%= category.text %>
     <% end %>
   <% end %>
   <%= f.label :body, '材料'%>
   <%= f.text_area :recipe_food, class:"form-control", placeholder:"材料をここに" %>
   <%= f.label :body, '作業工程'%>
   <%= f.text_area :recipe_body, class:"form-control", placeholder:"作業工程をここに" %><br>
   <%= f.submit "レシピ投稿", class: "btn btn-warning" %>
 <% end %>
```

collection_check_boxesというViewヘルパー関数を使って複数選択できるチェックボックスを実装しています。

```ruby:app/controllers/recipe_controller.rb
class RecipesController < ApplicationController
def new
    @recipe = Recipe.new
  end

  def create
    @recipe = Recipe.new(recipe_params)
    @recipe.user_id = current_user.id
    @recipe.save!
    redirect_to recipe_path(@recipe)
  end

  private
  def recipe_params
    params.require(:recipe).permit(:recipe_title, :recipe_body, :image, :recipe_food, category_ids: [])
  end
end
```

category_ids はチェックボックスの各チェックに関連付けられるIDが入ります。

```erb:app/views/recipes/index.html.erb
<% @recipes.each do |recipe| %>
・
・
・
  <% recipe.categories.each do |category| %>
    <%= category.category_name %>
  <% end %>
<% end %>
```

上記の記述で、冒頭で表示した２枚目の画像のようにcategory_nameが表示されます。

#最後に
今回多対多のアソシエーション、collection_check_boxesメソッドについての実装をしました！
collection_check_boxesメソッドに関してはまだ理解が浅いので、もう少し深く勉強します:sweat:
長くなりましたが、ここまで見て頂きありがとうございました！！:bow:

#参考
https://qiita.com/sho012b/items/3a595fde14516081dff5
https://qiita.com/cawaz3/items/e755a58177212f2aca6c