LoginSignup
1
2

More than 3 years have passed since last update.

商品一覧ページ内のカートに入れるボタンの実装(非同期通信)

Last updated at Posted at 2020-04-13

はじめに

商品一覧ページ内の各商品に割り振られているカートに入れるボタンが押された際にuser_idとeffector_id(現在作成中のアプリケーションではエッフェクターが商品のため各所でeffectorを使用していく)にログイン中のuserのidとクリックされた商品のidを保存することを目指す。今回は非同期通信を使用したい。

テーブル、コントローラー、APIの作成

cartsテーブルの作成

ターミナル
アプリケーションのディレクトリ$ rails g model cart

cartモデルの作成

(migrateファイル)create_carts.rb
class CreateCarts < ActiveRecord::Migration[5.0]
  def change
    create_table :carts do |t|
      t.references :user, foreign_key: true
      t.references :effector, foreign_key: true
      t.timestamps
    end
  end
end

マイグレーションファイルの編集

ターミナル
アプリケーションのディレクトリ$ rails db:migrate

マイグレーションの実行

(modelファイル)cart.rb
class Cart < ApplicationRecord
  belongs_to :effector
  belongs_to :user
end
(modelファイル)effector.rb
class Effector < ApplicationRecord
  belongs_to :genre
  has_many :users, through: :carts
  #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要
  has_many :carts
end
(modelファイル)user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :boards
  has_many :effectors, through: :carts
  #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要
  has_many :carts
end

各モデル内にリレーションを記載

APIの準備

app/controller/api/carts_controller.rbを作成

app/controller/api/carts_controller.rb
class Api::CartsController < ApplicationController
  def create
    Cart.create(user_id: params[:user_id], effector_id: params[:effector_id])
    #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存
  end
end

ルーティング設定

routes.rb
Rails.application.routes.draw do
  root to: "effectors#index"
  devise_for :users
  resources :users, only: [:show, :edit, :update]
  resources :boards
  resources :effectors do
    resources :genres
  end
  resources :carts, only: [:show, :destroy]
  namespace :api do
    resources :carts, only: :create, defaults: { format: 'json'}
  end
  #cartsコントローラーとapp/controller/api/carts_controller.rbのルーティング設定
end

ここまで設定が終わったら商品一覧のカートに入れるボタンが押された際にcartsテーブルにuser_idとeffector_idが保存されるようにjsを記述していく。

商品一覧のカートに入れるボタンが押された時の処理

カートに入れるボタンが押された時onclick:を用いてjs内の関数を発火できるように記述する。

app/views/effectors/index.html.haml
.main
  .main__list
    - @effectors.each do |effector|
      .main__list__effector{data: {genre: effector.genre.id}}
        .main__list__effector__info
          .main__list__effector__info__visual
            %h.main__list__effector__info__visual__name
              = effector.name
            .main__list__effector__info__visual__image
              %img{alt: "image1", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image1}"}
              %img{alt: "image2", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image2}"}
          .main__list__effector__info__text
            %h.main__list__effector__info__text__genre
              = effector.genre.genre
            %h.main__list__effector__info__text__point
              = effector.point
              pt
            %br 
            %h.main__list__effector__info__text__detail
              = effector.text
          .main__list__effector__info__btns
            - if effector.youtube != nil
              .main__list__effector__info__btns__video
                %button.main__list__effector__info__btns__video__btn{onclick: "test(#{effector.youtube})"}
                  動画を視聴
            - if effector.link != nil
              .main__list__effector__info__btns__official
                = link_to "#{effector.link}", class: "main__list__effector__info__btns__official__btn" do
                  .main__list__effector__info__btns__official__btn__text
                    公式サイト
            - if user_signed_in?
              .main__list__effector__info__btns__cart
                %button.main__list__effector__info__btns__cart__btn{onclick: "createCart(#{current_user.id},#{effector.id})"}
                  -#クリックされた時関数名createCartを引数(current_user.id,effector.id)とし発火
                  カートに入れる
  .popup
    .popup__content
      .popup__content__youtube
        %iframe(width="560" height="315" id = "youtube_test" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen)
      %button#close
        閉じる

発火される関数の記述

effectors.js
function createCart(userId, effectorId) {
  var param = {
    user_id: userId,
    effector_id: effectorId
    //受け取った引数をキーuser_id:とキーeffector_id:にそれぞれのバリューとして変数paramに格納
  }
  ajaxRequest("api/carts",'post',param)
  //非同期通信する際の関数を複数回の利用を見越して外出しして呼び出す(引数をapi/carts,post,paramとし呼び出し)
}

function ajaxRequest(url,type,data) {
  $.ajax({
    url: url,
    //url: api/cartsと同義
    type: type,
    //type: postと同義
    dataType: 'json',
    data: data
    //data: paramと同義
    //引数で持ってきた仮引数url,type,dataを使用しajaxの記述をする
  })
  .done(function() {
    alert('商品をカートに入れました')
  })
  .fail(function() {
    alert('error');
  });
}

ここまできたらjson形式で送られたデータをapi側のコントローラーで保存してあげるだけである。
先ほど記述したapp/controller/api/carts_controller.rbを見てみる

app/controller/api/carts_controller.rb
class Api::CartsController < ApplicationController
  def create
    Cart.create(user_id: params[:user_id], effector_id: params[:effector_id])
    #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存
  end
end

すでに記載している通りにjosn形式で送られてきたデータからcartsテーブルのuser_idカラムにparams[:user_id]をeffector_idカラムにparams[:effector_id]を保存する記載をする。
これにてカートに入れるボタンの実装が完了します。

終わりに

今回はカートに入れるボタンというショッピングサイトには欠かせない機能を非同期通信にて行えるように実装した。
ユーザーと商品という多対多という関係性、非同期通信でのデータの保存など初学者が苦労する機能の実装を行うことで力がつくのを感じました。
この機能はいいね機能などにも流用できると思うので学習する価値ありだと感じます。
2回目の投稿のため拙い文章が眼に余るかと思いますがご精読ありがとうございました。駆け出しエンジニアのみなさん一緒に頑張っていきましょう。

1
2
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
1
2