はじめに
某プログラミングスクールでフリマアプリを作成中、購入内容の確認ページからクレジットカード登録ページに遷移。カード登録後、購入内容の確認ページに遷移することが出来なくなった。
原因:コントローラーがitems_controller.rbからcredit_cards_controller.rbに変わった時点でパラメータの:item_idが0になっていた。
詳細
- ユーザーログイン後、routingでトップページ(items#index)へ遷移。
- 他ユーザーの出品商品(items#create)の詳細ページ(items#show)へ遷移。
- 詳細ページ(items#show)の購入ボタンより商品購入ページ(items#purchase)へ遷移。
- クレジットカード情報の登録・変更するために、登録・変更ボタンより(credit_cards#index)へ遷移。
- 遷移したが変更がなければ、もどるボタンで商品購入ページ(items#purchase)へ遷移。
- 変更・未登録ならカード登録ページ(credit_cards#new,create)に遷移後,(credit_cards#show)に遷移。その後カード決定・もどるボタンより商品購入ページ(items#purchase)へ遷移。
resources :items, only: [:index, :new, :create, :show, :edit, :destroy] do
get '/purchase/:id', to: 'items#purchase', as: :purchase
end
resources :credit_cards, only: [:index, :new, :create, :show, :destroy]
5. 4-1,4-2にてitem_idがないというErrorが発生した
ターミナルで確認するとitem_idがcontrollerを跨ぐタイミングで消えている。
Processing by ItemsController#purchase as HTML
Parameters: {"item_id"=>"2"}
Item Load (0.3ms) SELECT `items`.* FROM `items` WHERE `items`.`id` = 2 LIMIT 1
Processing by CreditCardsController#show as HTML
実装内容
item_idを引き継ぐ方法を検索していたところ...
sessionが使えそうだと判断。
はじめにapplication_controller.rbにinclude SessionHelperを追加。
class ApplicationController < ActionController::Base
include SessionsHelper #左記を追加
end
/app/helpersに/sessions_helper.rbを作成し、下記コードでSessionsHelperを呼び出し
module SessionsHelper
end
参考記事
「初期化されていない定数ApplicationController :: SessionsHelper(NameError)」が表示されるのはなぜですか?
これでsessionの準備が完了
まず、sessionにitem_idを保存する。
def purchase
@item = Item.find(params[:item_id]) #paramsからitem_idを取り出し
session[:item_id] = @item #取り出したitem_idをsessionに保存
end
次に、credit_card登録先のcontroller(credit_cards#index,credit_cards#show)でsessionに保存していたパラメータを取り出す。
binding.pryで確認したところ配列になっていたので、valuesで取り出す。
#session[:item_id]で先ほどのsessionデータを取り出せる。
def index
@item_id = session[:item_id].values.first
end
def show
@item_id = session[:item_id].values.first
end
controllerで作成したインスタンス変数(@item_id)をviewで取り出し
= link_to "もどる", "/items/#{@item_id}/purchase", class:'return'
%button.enter__permit__box.btn(onclick="location.href='/items/#{@item_id}/purchase'")選択した支払い方法を使う
= link_to "もどる", "/items/#{@item_id}/purchase", class:'return'
これで items#purchase ⇄ credit_cards#show,index において item_idのやりとりが出来るようになった。
最後に商品購入をした際に、sessionの削除をする
def pay
session[:item_id] = nil
end
今回はsessionを使ってパラメータのやりとりを行なったがURLを使用してパラメータをやりとりできるみたいなので、今度試してみたい。
なお、sessionを使用する際は、それなりにリスクを伴うので、使用する際は下記のリンク先も合わせて読んでおきたい。