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

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

Ruby on RailsでWebアプリケーション開発その21 買い物カートのマイグレーション

<<前  [TOP]  次>>


現在のカートの状態は別々に表示された商品と数量が2つの商品が混在しています。
ここでその複数行を1つにまとめるという処理を行います。


まずはマイグレーションの作成です。
コマンドプロンプトで「shop」フォルダに移動し、「rails generate migration combine_items_in_cart」と入力します。
f:id:MrRadiology:20180222110926p:plain


「migrate」フォルダに作成された「combine_items_in_cart.rb」ファイルを以下のように編集します。


【db/migrate/combine_items_in_cart.rb】

class CombineItemsInCart < ActiveRecord::Migration
  def up
	Cart.all.each do |cart|
		sums = cart.line_items.group(:good_id).sum(:quantity)

		sums.each do |good_id, quantity|
			if quantity > 1
				cart.line_items.where(good_id: good_id).delete_all
				cart.line_items.create(good_id: good_id, quantity: quantity)
			end
		end
	end
  end
end

カート内に1つの商品に対して複数のline_itemがあった場合は、1つのline_itemに置き換えるという処理をします。
まず「sums = cart.line_items.group(:good_id).sum(:quantity)」でカート内の各商品の数をカウントします。
各カートに関連付けられたline_itemのquantityフィールドの合計をグループ化して求めています。
合計数量が2以上の場合は、このカートと関連付けられた個別のline_itemをすべて削除し、正しい数量を持つline_item1つに置き換えます。
line_itemを削除するのが「cart.line_items.where(good_id: good_id).delete_all」で、置き換えるのが「cart.line_items.create(good_id: good_id, quantity: quantity)」の部分です。


「rake db:migrate」を実行します。
f:id:MrRadiology:20180222110849p:plain


カートの内容が商品ごとにまとめられました。
f:id:MrRadiology:20180222122926p:plain


次に元に戻す「down()」メソッドも実装しておきます。
「combine_items_in_cart.rb」ファイルを以下のように編集します。


【db/migrate/combine_items_in_cart.rb】

class CombineItemsInCart < ActiveRecord::Migration
  def up
	Cart.all.each do |cart|
		sums = cart.line_items.group(:good_id).sum(:quantity)

		sums.each do |good_id, quantity|
			if quantity > 1
				cart.line_items.where(good_id: good_id).delete_all
				cart.line_items.create(good_id: good_id, quantity: quantity)
			end
		end
	end
  end

  def down
	LineItem.where("quantity>1").each do |line_item|

		line_item.quantity.times do
			LineItem.create cart_id: line_item.cart_id, good_id: line_item.good_id, quantity: 1
		end

		line_item.destroy
	end
  end
end

数量が2以上のline_itemを見つけ、このカートと商品にそれぞれ数量1で新しいline_itemを追加し、最後に元のline_itemを削除します。


「rake db:rollback」を実行すると、「down()」メソッドが実行されロールバックされ、元の状態に戻りますが、今回はロールバックせずこのままの進めていきます。


<<前  [TOP]  次>>