学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails

Ruby on Rails 6.0によるWebアプリケーション開発24 Ajaxの追加

<<前  [TOP]  次>>


ショッピングカートをAjaxスタイルにします。
ショッピングカート用のページを新たに開くのではなく、カタログページのサイドバーに現在のカートを配置することにします。
その後でページ全体を再表示しなくてもサイドバー内のカートを更新できるようにします。
まずはカートを専用ページからサイドバーに移動させます。
これには部分テンプレートを使います。
部分テンプレートとはビューの一部を専用のショッピングカートをAjaxスタイルにします。
ショッピングカート用のページを新たに開くのではなく、カタログページのサイドバーに現在のカートを配置することにします。
その後でページ全体を再表示しなくてもサイドバー内のカートを更新できるようにします。
まずはカートを専用ページからサイドバーに移動させます。
これには部分テンプレートを使います。
部分テンプレートとはビューの一部を専用のファイルに収めたものです。
別のテンプレートやコントローラから部分テンプレートを呼び出す(レンダリングする)ことができ、部分テンプレートは自身をレンダリングして結果を返します。
メソッドのように部分テンプレートにパラメータを渡すこともできます。
これにより同じ部分テンプレートで異なるレンダリング結果を得ることもできます。


「C:\Rails6\work\shop\app\views\carts」フォルダの「show.html.erb」ファイルを以下のように編集します。


【C:\Rails6\work\shop\app\views\carts\show.html.erb】

<article>
	<% if notice %>
		<aside id="notice"><%= notice %></aside>
	<% end %>

	<h2>カートの内容</h2>

	<table>
		<%= render(@cart.line_tems) %>

		<tfoot>
			<tr>
				<th colspan="2">合計:</th>
				<td class="price"><%= number_to_currency(@cart.total_price) %></td>
			</tr>
		</tfoot>
	</table>

	<%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %>
</article>



「render()」メソッドは渡されたコレクションに対する繰り返し処理を行います。
部分テンプレートはそれ自体独立した1つのテンプレートファイルです。
デフォルトではレンダリング対象のオブジェクトと同じディレクトリに配置し、テーブル名と同じ名前にします。
通常テンプレートの名前と区別するためファイルの検索時に部分テンプレートの名前の先頭に自動的にアンダーズコア(_)を追加します。
「C:\Rails6\work\shop\app\views\line_items」フォルダ内にファイルを「_line_item.html.erb」という名前で新規作成します。


【C:\Rails6\work\shop\app\views\line_items\_line_item.html.erb】

<tr>
	<td><%= line_item.good.title %></td>
	<td class="quantity"><%= line_item.quantity %></td>
	<td class="price"><%= number_to_currency(line_item.total_price) %></td>
</tr>



部分テンプレートの内部ではテンプレート名と同じ名前の変数を使って現在のオブジェクトを参照できます。
この部分テンプレートは「lineitem」という名前なので、その中では「line_item」という変数を使えます。


LineItemに部分テンプレートを使ったのでカートでも同じことをします。
まず「_cart.html.erb」テンプレートを作成し、@cartではなくcartを使います。
「C:\Rails6\work\shop\app\views\carts」フォルダ内にファイル「_cart.html.erb」を新規作成します。
内容は「C:\Rails6\work\shop\app\views\carts\show.html.erb」ファイルとほぼ同じですが「<%= render(cart.line_items) %>」の記述を追加しています。


【C:\Rails6\work\shop\app\views\carts\_cart.html.erb】

<article>
	<% if notice %>
		<aside id="notice"><%= notice %></aside>
	<% end %>

	<h2>カートの内容</h2>

	<table>
		<tr>
			<th>商品名</th>
			<th>数量</th>
			<th>価格</th>
		</tr>

		<%= render(cart.line_items) %>

		<tfoot>
			<tr>
				<th colspan="2">合計:</th>
				<td class="price"><%= number_to_currency(@cart.total_price) %></td>
			</tr>
		</tfoot>
	</table>

	<%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %>
</article>



このままでは「show.html.erb」と「_cart.html.erb」の全く同じ内容のファイルができてしまうので元のテンプレートを部分テンプレートをレンダリングするコードに置き換えます。
「C:\Rails6\work\shop\app\views\carts\show.html.erb」ファイルを以下のように編集します。


【C:\Rails6\work\shop\app\views\carts\show.html.erb】

<%= render @cart %>



次にアプリケーションのレイアウトを変更してサイドバーに新しいテンプレートを組み込みます。
「C:\Rails6\work\shop\app\views\layouts」フォルダにある「application.html.erb」ファイルを以下のように編集します。
サイドバーの部分に「

<%= render @cart %>
」の記述を追加します。


【C:\Rails6\work\shop\app\views\layouts\application.html.erb】

<!DOCTYPE html>
<html>
  <head>
    <title>Railsはじめてマート オンラインストア</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
	<header class="main">
		<%= image_tag 'logo.png', alt: 'Railsはじめてマート',  width: 80 %>
	</header>
	<section class="content">
		<nav class="side_nav">
			<div id="cart" class="carts">
				<%= render @cart %>
			</div>
			<ul>
				<li><a href="/">ホーム</a></li>
				<li><a href="/questions">質問</a></li>
				<li><a href="/news">ニュース</a></li>
				<li><a href="/contact">問い合わせ</a></li>
			</ul>
		</nav>
		<main class='<%= controller.controller_name %>'>
		    <%= yield %>
		</main>

	</section>
  </body>
</html>



コントローラの変更を行います。
「C:\Rails6\work\shop\app\controllers」フォルダにある「market_controller.rb」ファイルを以下のように編集します。
「include CurrentCart」と「before_action :set_cart」の記述を追加しています。


【C:\Rails6\work\shop\app\controllers\market_controller.rb】

class MarketController < ApplicationController

  include CurrentCart
  before_action :set_cart

  def index
	@goods = Good.order(:title)
  end
end



最後にスタイルシートを変更します。
まずは「C:\Rails6\work\shop\app\assets\stylesheets\application.css」の編集です。
以下の記述を追加します。


【C:\Rails6\work\shop\app\assets\stylesheets\application.css】

article {
	padding: 1.414em;
	background: white;
	border-radius: 1.5em;
	margin: 1.414em;
	font-size: smaller;
}



「カートに入れる」ボタンの動作を変更します。
カート用のページは表示しないようにしてメインのインデックスページを更新するだけにします。
「C:\Rails6\work\shop\app\controllers」フォルダにある「line_items_controller.rb」ファイルを以下のように編集します。
「create()」メソッドの「format.html { redirect_to market_index_url }」の部分を変更するだけです。


【C:\Rails6\work\shop\app\controllers\line_items_controller.rb】

 class LineItemsController < ApplicationController

	include CurrentCart
	before_action :set_cart, only: [:create]
	before_action :set_line_item, only: [:show, :edit, :update, :destroy]

  # GET /line_items
  # GET /line_items.json
  def index
    @line_items = LineItem.all
  end

  # GET /line_items/1
  # GET /line_items/1.json
  def show
  end

  # GET /line_items/new
  def new
    @line_item = LineItem.new
  end

  # GET /line_items/1/edit
  def edit
  end

  # POST /line_items
  # POST /line_items.json
  def create

	good = Good.find(params[:good_id])
	@line_item = @cart.add_good(good)

    respond_to do |format|
      if @line_item.save
        format.html { redirect_to market_index_url }
        format.json { render :show, status: :created, location: @line_item }
      else
        format.html { render :new }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /line_items/1
  # PATCH/PUT /line_items/1.json
  def update
    respond_to do |format|
      if @line_item.update(line_item_params)
        format.html { redirect_to @line_item, notice: '品目が更新されました。' }
        format.json { render :show, status: :ok, location: @line_item }
      else
        format.html { render :edit }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /line_items/1
  # DELETE /line_items/1.json
  def destroy
    @line_item.destroy
    respond_to do |format|
      format.html { redirect_to line_items_url, notice: '品目を破棄しました。' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_line_item
      @line_item = LineItem.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def line_item_params
      params.require(:line_item).permit(:good_id, :cart_id)
    end
end



http://localhost:3000/]にアクセスしてブラウザの表示を確認してみます。

ブラウザの表示
ブラウザの表示


<<前  [TOP]  次>>