#はじめに
商品一覧ページ内の各商品に割り振られているカートに入れるボタンが押された際にuser_idとeffector_id(現在作成中のアプリケーションではエッフェクターが商品のため各所でeffectorを使用していく)にログイン中のuserのidとクリックされた商品のidを保存することを目指す。今回は非同期通信を使用したい。
#テーブル、コントローラー、APIの作成
##cartsテーブルの作成
アプリケーションのディレクトリ$ rails g model cart
cartモデルの作成
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
マイグレーションの実行
class Cart < ApplicationRecord
belongs_to :effector
belongs_to :user
end
class Effector < ApplicationRecord
belongs_to :genre
has_many :users, through: :carts
#今回はcartsコントローラーのshowアクションを使用するため上の記述は不要
has_many :carts
end
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を作成
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
ルーティング設定
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内の関数を発火できるように記述する。
.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
閉じる
###発火される関数の記述
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を見てみる
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回目の投稿のため拙い文章が眼に余るかと思いますがご精読ありがとうございました。駆け出しエンジニアのみなさん一緒に頑張っていきましょう。