❶新規出品ページアクセスの詳細フロー
[トップページ]
↓ 出品するボタンをクリック(link_to などのリンクを踏む)
GET /items/new
↓ ルーティングが反応(config/routes.rb で行き先を決定)
ItemsController#new
↓ (ここで @item = Item.new を実行し、空の箱を作る)
app/views/items/new.html.erb が表示される
(コントローラーで作った @item がビューに渡され、入力フォームが表示され
⬇︎⬇︎⬇︎
❷ 新規出品ページで出品作業を行う
[出品画面(new.html.erb)]
↓ 必要な情報を入力し、「出品する」ボタンをクリック
POST /items
↓ ルーティングが反応(config/routes.rb の resources :items が POST リクエストを検知)
ItemsController#create
↓ (ここで Item.new(item_params) を実行し、中身の詰まった箱を作る)
↓ (@item.save により、データベースのテーブルへ保存を実行)
[トップページ] へリダイレクト
↓ 保存成功後、redirect_to root_path によって画面が切り替わる
(失敗した場合は render :new により出品画面が再表示される)
❶新規出品ページアクセスの詳細フロー
1リクエスト
『出品する』をクリックする
2ルーティング
HTTPリクエスト: GET /items/new がサーバーへ送られる。
% rails routes
の「new_item GET /items/new items#new」が反応する

補足 ルーティング表の見方
https://qiita.com/358TECH-CAMP/items/4fdb04549404abe85bc2
補足

Railsの判断: config/routes.rb を確認。
一致する定義: get '/items/new', to: 'items#new'(または resources :items の一部)が反応。
行き先: items コントローラーの new アクションへ案内。
左を簡略したものが右の書き方
resources :items, only: [:index, :new, :create, :show, :edit, :update, :destroy] do
resources :orders, only: [:index, :create]
end
items に関する 7つのルーティング(※上の青枠の方) と
items に紐づく orders に関する 2つのルーティング を
Railsが自動生成している
(補足)resourcesの仕組みとメリット
https://qiita.com/358TECH-CAMP/items/699cbd55bb5410b991b7
3.コントローラー (Controller)
処理: items_controller.rb の def new が実行される。
内容: @item = Item.new によって、空の商品の箱(インスタンス)を作成。
4.レスポンス (Response)
表示: views/items/new.html.erb (出品画面)をブラウザに返して表示。

最終的に、HTML(views/items/new.html.erb)がHTTP通信に乗ってブラウザに返され、画面が表示されます。

表示されているコードの中身の全部は以下の通り
<div class="items-sell-contents">
<header class="items-sell-header">
<%= link_to image_tag('furima-logo-color.png', size: '185x50'), root_path %>
</header>
<div class="items-sell-main">
<h2 class="items-sell-title">商品の情報を入力</h2>
<%= form_with model: @item, local: true, html: { multipart: true } do |f| %>
<%= render 'shared/error_messages', model: f.object %>
<%# --- 商品画像 --- %>
<div class="img-upload">
<div class="weight-bold-text">
商品画像 <span class="indispensable">必須</span>
</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 :name, class: "items-text", id: "item-name", placeholder: "商品名(必須 40文字まで)", maxlength: 40 %>
<div class="items-explain">
<div class="weight-bold-text">
商品の説明 <span class="indispensable">必須</span>
</div>
<%# :description から :info に修正しました %>
<%= f.text_area :info, class: "items-text", id: "item-info", placeholder: "商品の説明(必須 1,000文字まで)", 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" } %>
<div class="weight-bold-text">商品の状態 <span class="indispensable">必須</span></div>
<%# :status_id から :sales_status_id に修正しました %>
<%= f.collection_select :sales_status_id, SalesStatus.all, :id, :name, {}, { class: "select-box" } %>
</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>
<%# :delivery_fee_id から :shipping_fee_status_id に修正しました %>
<%= f.collection_select :shipping_fee_status_id, ShippingFeeStatus.all, :id, :name, {}, { class: "select-box" } %>
<div class="weight-bold-text">発送元の地域 <span class="indispensable">必須</span></div>
<%= f.collection_select :prefecture_id, Prefecture.all, :id, :name, {}, { class: "select-box" } %>
<div class="weight-bold-text">発送までの日数 <span class="indispensable">必須</span></div>
<%= f.collection_select :scheduled_delivery_id, ScheduledDelivery.all, :id, :name, {}, { class: "select-box" } %>
</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 :price, class: "price-input", id: "item-price", placeholder: "例)300" %>
</div>
<div class="price-content"><span>販売手数料 (10%)</span> <span><span id='add-tax-price'></span>円</span></div>
<div class="price-content"><span>販売利益</span> <span><span id='profit'></span>円</span></div>
</div>
</div>
<%# --- ボタン --- %>
<div class="sell-btn-contents">
<%= f.submit "出品する", class: "sell-btn" %>
<%= link_to 'もどる', root_path, class: "back-btn" %>
</div>
<% end %>
</div>
<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'), root_path %>
<p class="inc">©︎Furima,Inc.</p>
</footer>
</div>
❷ 新規出品ページで出品作業を行う
1 リクエスト
出品画面(VCコード:ファイルパスnew.html.erb)にて
商品情報を入力し、「出品する」ボタンをクリック

2ルーティング
% rails routes の POST /items(.:format) items#createが反応
config/routes.rb の設定に基づき、赤線部分(詳細は赤枠の箇所)が反応
resources :items, only: [:index, :new, :create, :show, :edit, :update, :destroy] do
3.コントローラー (Controller)
ItemsController#create
(ここで Item.new(item_params) を実行し、ユーザーが入力した中身の詰まった箱を作る)
(@item.save により、データベースのテーブルへ保存を実行)
4.モデル
モデル(Active Record)の内部挙動まとめ
- バリデーションの自動実行(保存前の検品)
ユーザーが「出品する」ボタンを押し、コントローラーで @item.save が呼ばれた瞬間に作動します。
読み込み: item.rb に書かれた validates :shipping_fee_status_id, presence: true などのルールを確認します。

判定: schema.rb の設計図と照らし合わせ、データが不足していれば「保存中止」を決定します。

返り値: 保存不可なら false を、保存完了なら true をコントローラーに返します。
- エラー情報のパッキング(errors ポケットへの収納)
バリデーションで「保存中止」になった場合、モデルはただ止まるだけではありません。
自動生成: 「shipping_fee_status_id が blank(空)だった」という事実を検知します。
収納: @item インスタンスの中にある errors という特別な場所に、"can't be blank" というメッセージを自動で書き込みます。
受け渡し: このメッセージを持ったままの @item が、コントローラーを介してビューへ渡されます。
4.レスポンス (エラーの場合:"can't be blank" )
■失敗時:render :new
表示されるビュー: views/items/new.html.erb (出品画面)
動き: 別の場所へ移動せず、今の create アクションの中に居たまま「もう一度、出品用の見た目(HTML)を作って!」とビューに依頼します。
ユーザーの体験: 入力した内容が残ったまま、赤い文字で「価格を入力してください」などのエラーメッセージが表示された「元の入力画面」に戻ります。
4モデル (trueの場合の処理)
データベース(SQL)への翻訳と実行
バリデーションを無事にクリア(true)した場合のみ、このステップへ進みます。
ORM機能: Rubyのオブジェクト形式である @item を、データベースが理解できる「SQL文」へ自動翻訳します。
書き込み: schema.rb で定義された items テーブルの適切なカラム(name, price など)へデータを流し込みます。
(例)Usersテーブルの場合
https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4335921%2F9ed51d35-87cd-4931-a864-f27ed58526d9.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=868440e03462e6d717ab46b925304403
① コントローラー ※4モデル (trueの場合の処理)
リダイレクトの指示(次にどこへ行くかの判断)
保存が成功すると、コントローラーがブラウザに「次はこのURLへ行け」と命令を出します。
場所
app/controllers/items_controller.rb
コード
redirect_to root_path
HTTP通信
ブラウザに対して「HTTP 302 (Found)」というステータスコードを返します。
この時、ブラウザの住所録(URL)を書き換えるよう指示します。
②ルーティング ※4モデル (trueの場合の処理)
新しいリクエストの受付(ブラウザ → Rails)
ブラウザは命令に従い、自動的にトップページへアクセスし直します。
リクエスト
GET /(HTTPメソッドのGETでルートパスを要求)
ルーティング照合
config/routes.rb の
root to: "items#index"
を読み取り、ItemsController の index アクションへ案内します。
③ コントローラー ※4モデル (trueの場合の処理)
一覧データの取得(データベース → ビュー準備)
トップページを表示するために、最新のデータを取り出します。
場所
app/controllers/items_controller.rb
アクション
def index
@items = Item.all.order("created_at DESC")
end
動き
データベースの items テーブルから全商品を取得し、新着順に並べた
@items をビューへ渡します。
④ ビュー ※4モデル (trueの場合の処理)
最終的な画面表示(ユーザーが見る世界)
ユーザーの目に映る最終的な景色です。
表示されるファイルパス
app/views/items/index.html.erb
内容
@items の中身(先ほど保存した商品を含む)がHTMLとして組み立てられ、
ブラウザに表示されます。






