商品投稿　enum

### はじめに
**:shamrock:管理者側から商品を投稿して顧客の商品一覧ページに表示させます。**

ステータスはenumで実装しました。
bootstrap導入済み
devaice導入済み
____
migrateファイルはこんな感じ
```diff_ruby
class CreateItems < ActiveRecord::Migration[6.1]
  def change
    create_table :items do |t|
      t.string :name, null: false
      t.text :description, null: false
      t.integer :price, null: false
      t.boolean :is_active, null: false, default: true
      t.timestamps
    end
  end
end
```

### :shamrock:モデルの設定
```item.rb
class Item < ApplicationRecord
  has_one_attached :image
 enum status: { on_sale: 0, off_sale: 1 }
end
```
:star:**has_one_attached :image**
 は、Active Storage（Railsのファイルアップロードを担当する部分）に対する指示で、各Itemレコードが一つのimageファイルを持つことを示しています。

:star:**enum status: { on_sale: 0, off_sale: 1 }**
は、statusという名前の列があることを示しています。status列は整数型で、on_saleが0、off_saleが1としてマッピングされます。これにより、Itemの状態を文字列ではなく整数でデータベースに保存でき、それによりパフォーマンスを向上させ、コード内で直感的にその状態を理解できます。







### :shamrock:コントローラの設定
```admin/items/controller.rb
class Admin::ItemsController < ApplicationController
  def new
    @item = Item.new
  end

  def create
    @item = Item.new(item_params)
    if @item.save
      redirect_to admin_items_path
    else
      render :new
    end
  end

  private

  def item_params
    params.require(:item).permit(:name, :description, :price, :status, :image)
  end
end
```
:star:**newアクション**
 新規Itemオブジェクトを作成し、それを@itemというインスタンス変数に代入します。このアクションは、新規作成フォームの表示を担当します。

:star:**createアクション**
フォームからのデータ（パラメータ）を用いて新規Itemオブジェクトを作成します。作成が成功した場合、商品一覧ページ(admin_items_path)にリダイレクトします。失敗した場合は、新規作成フォームを再度表示します。

:star:**item_params**
 ストロングパラメータ（Strong Parameters）と呼ばれる機能を使用して、フォームから送信されたデータのうち、どのデータを許可するか(受け取るか）を指定しています。これは、不正なデータを防ぐためのセキュリティ機能です。

:star:**private**
は、その下に定義されたメソッドがプライベート（このクラスの内部からのみアクセス可能）であることを示します。これにより、他の部分から直接これらのメソッドを呼び出すことはできません。







### veiws 商品投稿ページ
```erb:admin/items/new.haml.erb
<h3 class="text-center">商品新規登録</h3>
<%= form_with model: [:admin, @item], local: true, class: 'col-6 mx-auto' do |f| %>
  <div class="form-group row">
    <%= f.label :image, '商品画像', class: 'col-sm-3 col-form-label' %>
    <div class="col-sm-9">
      <%= f.file_field :image, class: 'form-control' %>
    </div>
  </div>
  <div class="form-group row">
    <%= f.label :name, '商品名', class: 'col-sm-3 col-form-label' %>
    <div class="col-sm-9">
      <%= f.text_field :name, class: 'form-control' %>
    </div>
  </div>
  <div class="form-group row">
    <%= f.label :description, '商品説明', class: 'col-sm-3 col-form-label' %>
    <div class="col-sm-9">
      <%= f.text_area :description, class: 'form-control' %>
    </div>
  </div>
  <div class="form-group row">
    <%= f.label :price, '税抜価格', class: 'col-sm-3 col-form-label' %>
    <div class="col-sm-9 input-group">
      <%= f.number_field :price, class: 'form-control' %>
      <div class="input-group-append">
        <span class="input-group-text">円</span>
      </div>
    </div>
  </div>
  
  <div class="form-group row">
  <%= f.label :status, '販売ステータス', class: 'col-sm-3 col-form-label' %>
  <div class="col-sm-9">
    <div class="custom-control custom-radio custom-control-inline">
      <%= f.radio_button :status, 'on_sale', checked: @item.status == 'on_sale', class: 'custom-control-input', id: 'status-on-sale' %>
      <%= f.label :status, '販売中', class: 'custom-control-label', for: 'status-on-sale' %>
    </div>
    <div class="custom-control custom-radio custom-control-inline">
      <%= f.radio_button :status, 'off_sale', checked: @item.status == 'off_sale', class: 'custom-control-input', id: 'status-off-sale' %>
      <%= f.label :status, '販売停止中', class: 'custom-control-label', for: 'status-off-sale' %>
    </div>
  </div>
</div>


  </div>
  <div class="form-group row">
    <div class="col-sm-9 offset-sm-3">
      <%= f.submit '新規投稿', class: 'btn btn-success text-white' %>
    </div>
  </div>
<% end %>
```
### :cherry_blossom:販売ステータスについて
```erb
<div class="form-group row">
  <%= f.label :status, '販売ステータス', class: 'col-sm-3 col-form-label' %>
  <div class="col-sm-9">
```
:star:上記の部分はブートストラップのクラスを使用してレイアウトを作成しています。:statusは商品のステータス（販売中か販売停止中か）を示す属性です。
```erb
    <div class="custom-control custom-radio custom-control-inline">
      <%= f.radio_button :status, 'on_sale', checked: @item.status == 'on_sale', class: 'custom-control-input', id: 'status-on-sale' %>
      <%= f.label :status, '販売中', class: 'custom-control-label', for: 'status-on-sale' %>
    </div>
```
:star:この部分では、on_sale（販売中）というステータスを設定するラジオボタンを作成しています。 
**@item.status == 'on_sale'** という部分は、商品の現在のステータスが**on_sale** であれば、このラジオボタンが選択されるようにしています。
```erb
    <div class="custom-control custom-radio custom-control-inline">
      <%= f.radio_button :status, 'off_sale', checked: @item.status == 'off_sale', class: 'custom-control-input', id: 'status-off-sale' %>
      <%= f.label :status, '販売停止中', class: 'custom-control-label', for: 'status-off-sale' %>
    </div>
  </div>
</div>
```
:sunny:最後の部分は販売停止(off_sale)のステータスを設定するラジオボタンを作成しています。
**@item.status == 'off_sale'** という部分は、商品の現在のステータスが **off_sale** であれば、このラジオボタンが選択されるようにしています。

このように、管理者は商品のステータスを選択して、商品が販売中か販売停止中かを設定することができます。これらの設定はItemモデルの:status属性に保存されます。







_____
### 補足
以下のエラーが発生したら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492906/883e9529-966e-b88b-0366-fb4d1f804ceb.png)

このエラーは、Active Storageが適切にセットアップされていないことを示しています。Active Storageは、Railsでファイルアップロードを処理するためのフレームワークです。具体的には、active_storage_blobsテーブルがデータベースに存在しないために発生しています。
エラーメッセージにあるように、以下のコマンドを実行してActive Storageをセットアップし、必要なテーブルを作成します。
```
$ bin/rails active_storage:install
```
このコマンドを実行すると、必要なマイグレーションファイルが作成されます。その後、以下のコマンドを実行してマイグレーションをデータベースに適用します。

```
$ bin/rails db:migrate
```
これにより、Active Storageが適切に機能します



完成イメージ
![スクリーンショット 2023-07-19 14.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492906/8fdb6d90-9e47-39c3-103c-4c4e6c5051a6.png)