0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画面遷移の流れ(新規→投稿完了)

0
Last updated at Posted at 2026-02-08

❶新規出品ページアクセスの詳細フロー

[トップページ]

↓ 出品するボタンをクリック(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リクエスト

『出品する』をクリックする

スクリーンショット 0008-02-08 9.59.37.png

2ルーティング 

HTTPリクエスト: GET /items/new がサーバーへ送られる。

% rails routes
の「new_item GET /items/new items#new」が反応する
スクリーンショット 0008-02-08 10.08.36.png
補足 ルーティング表の見方
https://qiita.com/358TECH-CAMP/items/4fdb04549404abe85bc2
補足
スクリーンショット 0008-02-08 9.32.50.png

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が自動生成している

スクリーンショット 0008-02-08 9.22.07.png

(補足)resourcesの仕組みとメリット
https://qiita.com/358TECH-CAMP/items/699cbd55bb5410b991b7

3.コントローラー (Controller)

処理: items_controller.rb の def new が実行される。
内容: @item = Item.new によって、空の商品の箱(インスタンス)を作成。

スクリーンショット 0008-02-08 11.03.23.png

4.レスポンス (Response)

表示: views/items/new.html.erb (出品画面)をブラウザに返して表示。
スクリーンショット 0008-02-08 11.50.09.png
最終的に、HTML(views/items/new.html.erb)がHTTP通信に乗ってブラウザに返され、画面が表示されます。
スクリーンショット 0008-02-08 11.55.11 1.png

表示されているコードの中身の全部は以下の通り

<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)にて
商品情報を入力し、「出品する」ボタンをクリック
スクリーンショット 0008-02-08 12.20.04.png

2ルーティング

% rails routes の POST /items(.:format) items#createが反応

スクリーンショット 0008-02-08 12.38.09.png

config/routes.rb の設定に基づき、赤線部分(詳細は赤枠の箇所)が反応

  resources :items, only: [:index, :new, :create, :show, :edit, :update, :destroy] do

スクリーンショット 0008-02-08 12.25.40.png

3.コントローラー (Controller)

ItemsController#create
(ここで Item.new(item_params) を実行し、ユーザーが入力した中身の詰まった箱を作る)

(@item.save により、データベースのテーブルへ保存を実行)

スクリーンショット 0008-02-08 12.12.23.png

4.モデル

モデル(Active Record)の内部挙動まとめ

  1. バリデーションの自動実行(保存前の検品)
    ユーザーが「出品する」ボタンを押し、コントローラーで @item.save が呼ばれた瞬間に作動します。

読み込み: item.rb に書かれた validates :shipping_fee_status_id, presence: true などのルールを確認します。
スクリーンショット 0008-02-08 13.31.30.png

判定: schema.rb の設計図と照らし合わせ、データが不足していれば「保存中止」を決定します。
スクリーンショット 0008-02-08 13.35.22.png

返り値: 保存不可なら false を、保存完了なら true をコントローラーに返します。

  1. エラー情報のパッキング(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)を作って!」とビューに依頼します。

ユーザーの体験: 入力した内容が残ったまま、赤い文字で「価格を入力してください」などのエラーメッセージが表示された「元の入力画面」に戻ります。

スクリーンショット 0008-02-08 13.40.19.png

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として組み立てられ、
ブラウザに表示されます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?