オリジナルアプリ 〜wants〜　作成過程（リクエスト機能編）

### 本日の進捗報告: Wantsアプリのリクエスト機能実装（リクエスト投稿まで）

1. リクエストコントローラー・ビューの作成
1. リクエストモデルの作成
1. リクエストテーブルの設計とマイグレーション
1. ビュー新規依頼ページへのリンク作成
1. 画像保存用にactive storageの設定
1. カテゴリーなどの選択画面用にactivehashを設定
1. 投稿後トップページに戻る設定
1. バリデーションとエラーメッセージの表示の修正


色々つまづいた所もあって大変だったけどうまく動作できた時は感動した。まだまだ道程は長いけど12月までに完成させます！！
## 試作段階のビュー
![スクリーンショット 2024-10-29 18.30.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/59049062-6a01-0cfb-0f9b-858fb06e710f.png)
![スクリーンショット 2024-10-29 18.30.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/ca4c57ca-9673-ef64-77a3-5427212b263e.png)
![スクリーンショット 2024-10-29 18.30.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/0cc3f959-be2e-32f4-2548-472f4adc720b.png)
![スクリーンショット 2024-10-29 18.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/ea8123d3-3978-52fa-d9b8-72ae0d67ea9d.png)

## commitとテストの内容
![スクリーンショット 2024-10-29 19.26.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/2d676908-c99c-49a5-e52d-5e3f609a6f95.png)
![スクリーンショット 2024-10-29 19.28.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763893/0233d217-0f1e-b620-fb15-212a0845fbe9.png)

## 一部のコード
app/controllers/requests_controller.rb
```ruby
class RequestsController < ApplicationController
  def index
    @requests = Request.all
  end

  def new
    @request = Request.new # 新しいリクエストのインスタンスを作成
  end

  def create
    @request = Request.new(request_params) # リクエストの作成
    @request.user = current_user # ログインユーザーをリクエストのユーザーに設定

    if @request.save
      redirect_to root_path, notice: 'リクエストが作成されました。'
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def request_params
    params.require(:request).permit(:title, :description, :category_id, :max_price, :min_price, :image, :shipping_charge_id)
  end
end
```
---
app/views/requests/new.html.erb
```ruby
<div class="items-sell-contents">
  <header class="items-sell-header">
    <%= link_to image_tag('furima-logo-color.png' , size: '185x50'), "/" %>

  </header>
  <div class="items-sell-main">
    <h2 class="items-sell-title">商品の情報を入力</h2>
    <%= form_with model:@request, local: true do |f| %>

      <%= render 'shared/error_messages', model: @request %>

    <%# 商品画像 %>
    <div class="img-upload">
      <div class="weight-bold-text">
        画像
      </div>
      <div class="click-upload">
      <p>クリックしてファイルをアップロード</p>
        <%= f.file_field :image, id:"item-image" %>
      </div>
    </div>
    <%# /商品画像 %>
    <%# リクエストと概要 %>
    <div class="new-items">
      <div class="weight-bold-text">
        リクエスト名
        <span class="indispensable">必須</span>
      </div>
      <%= f.text_area :title, class:"items-text", id:"item-name", placeholder:"リクエスト名（必須 40文字まで)", maxlength:"40" %>
      <div class="items-explain">
        <div class="weight-bold-text">
          リクエストの説明・概要
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_area :description, class:"items-text", id:"item-info", placeholder:"リクエストの説明（必須 1,000文字まで）（色、素材、重さ、定価、注意点など）例）2010年頃に1万円で発売されたジャケットが欲しいです。ライトグレーで傷があっても構いません。サイズはLLでお願いします。" ,rows:"7" ,maxlength:"1000" %>
      </div>
    </div>
    <%# /商品名と商品説明 %>
    <%# /リクエストと概要 %>
    <%# 商品の詳細 %>
    <div class="items-detail">
      <div class="weight-bold-text">リクエストの詳細</div>
      <div class="form">
        <div class="weight-bold-text">
          カテゴリー
          <span class="indispensable">必須</span>
        </div>
          <%= f.collection_select(:category_id, Category.all, :id, :name, {}, {class:"select-box", id:"item-category"}) %>
      </div>
    </div>
    <%# /商品の詳細 %>

    <%# 配送について %>
    <div class="items-detail">
      <div class="weight-bold-text question-text">
        <span>配送について</span>
        <a class="question" href="#">?</a>
      </div>
      <div class="form">
        <div class="weight-bold-text">
          配送料の負担
          <span class="indispensable">必須</span>
        </div>
          <%= f.collection_select(:shipping_charge_id, ShippingCharge.all, :id, :name, {}, {class:"select-box", id:"item-shipping-fee-status"}) %>
      </div>
    </div>
    <%# /配送について %>

    <%# 販売価格 %>
    <div class="sell-price">
      <div class="weight-bold-text question-text">
        <span>希望価格<br>(¥300〜9,999,999)</span>
        <a class="question" href="#">?</a>
      </div>
      <div>
        <div class="price-content">
          <div class="price-text">
            <span>上限価格</span>
            <span class="indispensable">必須</span>
          </div>
          <span class="sell-yen">¥</span>
            <%= f.text_field :max_price, class:"price-input", id:"item-price", placeholder:"例）300" %>
        </div>
        <div class="price-content">
          <div class="price-text">
            <span>下限価格</span>
            <span class="indispensable">必須</span>
        </div>
          <span class="sell-yen">¥</span>
            <%= f.text_field :min_price, class:"price-input", id:"item-price", placeholder:"例）300" %>
        </div>
      </div>
    </div>
    <%# /販売価格 %>

    <%# 注意書き %>
    <div class="caution">
      <p class="sentence">
        <a href="#">禁止されている出品、</a>
        <a href="#">行為</a>
        を必ずご確認ください。
      </p>
      <p class="sentence">
        またブランド品でシリアルナンバー等がある場合はご記載ください。
        <a href="#">偽ブランドの販売</a>
        は犯罪であり処罰される可能性があります。
      </p>
      <p class="sentence">
        また、出品をもちまして
        <a href="#">加盟店規約</a>
        に同意したことになります。
      </p>
    </div>
    <%# /注意書き %>
    <%# 下部ボタン %>
    <div class="sell-btn-contents">
      <%= f.submit "依頼する" ,class:"sell-btn" %>
      <%=link_to 'もどる', root_path, class:"back-btn" %>
    </div>
    <%# /下部ボタン %>
  </div>
  <% end %>

  <footer class="items-sell-footer">
    <ul class="menu">
      <li><a href="#">プライバシーポリシー</a></li>
      <li><a href="#">フリマ利用規約</a></li>
      <li><a href="#">特定商取引に関する表記</a></li>
    </ul>
    <%= link_to image_tag('furima-logo-color.png', size: '185x50'), "/" %>
    <p class="inc">
      ©︎Wants,Inc.
    </p>
  </footer>
</div>
```
---
app/models/request.rb
```ruby
class Request < ApplicationRecord
  belongs_to :user
  has_many :products
  has_many :comments
  has_one_attached :image
  has_many :histories

  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :category
  belongs_to_active_hash :shipping_charge

  validates :title, :description, :category_id, :shipping_charge_id, presence: true
  validates :category_id, :shipping_charge_id, numericality: { other_than: 1, message: "can't be blank" }
  validates :max_price, :min_price, numericality: { only_integer: true, greater_than_or_equal_to: 300, less_than_or_equal_to: 9_999_999, message: "must be between 300 and 9999999" }
end

```