#エラー内容
フリマアプリ作成において、購入機能を実装中に起こったエラー
購入までの流れは、
1.商品一覧ページ
2.商品詳細ページ
--- ここでエラー ----
3.購入確認ページ
4.(購入完了)
Couldn't find Item with 'id'=
なので、「itemモデルのidが見つからない」とういエラーなます
#エラー原因
##コントローラー
まずエラーが出ているitmescontrollerについて
今回購入確認ページへのアクションはpurchase
、購入のアクションはbuy
とし、itmescontroller
に記述しています。purchase
,buy
アクションについてもitemのidを見つけるようにbefor_action
で設定していますので、コントローラーは問題なさそうです。
before_action :set_item, only: [:edit, :update, :destroy, :purchase, :buy]
#------省略--------
def purchase
card = Card.where(user_id: current_user.id).first
end
def buy
card = Card.where(user_id: current_user.id).first
Payjp.api_key = Rails.application.secrets.payjp_private_key
Payjp::Charge.create(
:amount => @item.price,
:customer => card.customer_id,
:currency => 'jpy',
)
redirect_to root_path
end
def set_item
@item = Item.find(params[:id])
end
def item_params
params.permit(
:name,
:item_condition_id,
:introduction,
:price,
:prefecture_code,
:trading_status,
:postage_payer_id,
:size_id,
:preparation_day_id,
:postage_type_id,
:category_id,
item_imgs_attributes: [:src, :_destroy, :id]
).merge(seller_id: current_user.id, trading_status: 0)
end
##ルーティング
次にpurchase
アクションを実行するためのルーティングをターミナルで確認します。
★★このルーティングの設定がエラーの原因でした。
purchase
アクションのURI Patternにidが入っていません。
ルーティングでidが入っていないのに、コントローラーでidの設定をしてるため、そりゃもちろんエラーになります。
($rails routes)
purchase_items GET /items/purchase(.:format) items#purchase
buy_items POST /items/buy(.:format) items#buy
ではルーティングの記述内容を確認し、修正します。
#ーーーーーーーー 修正前 ーーーーーーーーーー
resources :items do
collection do
get 'get_category_children', defaults: { format: 'json' }
get 'get_category_grandchildren', defaults: { format: 'json' }
get 'purchase', to: 'items#purchase'
post 'buy', to: 'items#buy'
end
end
#ーーーーーーーー 修正後 ーーーーーーーーーー
resources :items do
collection do
get 'get_category_children', defaults: { format: 'json' }
get 'get_category_grandchildren', defaults: { format: 'json' }
end
member do
get 'purchase', to: 'items#purchase'
post 'buy', to: 'items#buy'
end
end
上記の通り、resources :items do
でネストしている'purchase',buy
アクションのルーティングがcollection do
→member do
へと変更しています。
今回のようにidが必要な時はmember
、必要無い時はcollection
を使います。
修正後再度ターミナルで確認します
($rails routes)
purchase_items GET /items/:id/purchase(.:format) items#purchase
buy_items POST /items/:id/buy(.:format) items#buy
#ビュー
ルーティング変更に伴い、ページ移動のためのパスを変更して完了!!
(@item.id)
を忘れないよう注意しましょう。
(修正前)
.item-price__purchase-button
= link_to "購入画面に進む", purchase_items_path
(修正後)
.item-price__purchase-button
= link_to "購入画面に進む", purchase_item_path(@item.id)
#参考記事
エラー解決までに参考にした記事、または関連する箇所で勉強になった記事です。
Railsのルーティングの種類と要点まとめ
Ruby on Rails のエラーCouldn't find with id=が表示された際の3つの確認点