🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

DB2

DB2(IBM Database2)は、IBMのリレーショナルデータベース管理システム製品です。 UNIXとWindows、IBM社のメインフレームOS用が用意されており、 幅広いプラットフォームに対応しています。

Q&A

解決済

2回答

3145閲覧

購入情報をDBに保存したいです。

murohi-08

総合スコア12

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

DB2

DB2(IBM Database2)は、IBMのリレーショナルデータベース管理システム製品です。 UNIXとWindows、IBM社のメインフレームOS用が用意されており、 幅広いプラットフォームに対応しています。

0グッド

0クリップ

投稿2020/12/11 09:42

編集2020/12/12 05:17

購入機能の実装のところで、購入情報をDBに保存したいのですが、そのままリダイレクトせずトップページに遷移せず、そのページに残ってしまいます。User must exist, Item must existtoiuというエラーメッセージがブラウザ上に表示されるだけの状態になってしまいます。
どなたかご教授願えますでしょうか?よろしくお願いします。
イメージ説明

app/controllers/purchase_history_controller.rb class PurchaseHistoriesController < ApplicationController def index @user_item = UserItem.new @item = Item.find(params[:item_id]) end def create @item = Item.find(params[:item_id]) @user_item = UserItem.new(purchase_history_params) @user_item = SendingDestination.create @user_item = PurchaseHistory.create if @user_item.valid? @user_item.save redirect_to root_path else render action: :index end end private def purchase_history_params params.permit(:nickname, :email, :encrypted_password, :first_name, :family_name, :first_name_kana, :family_name_kana, :birth_day, :image, :name, :introduction, :category_id, :item_condition_id, :postage_id, :prefecture_id, :prepare_id, :price, :post_code, :prefecture_id, :city, :house_number, :building_name, :phone_number) end end
app/models/user_item.rb class UserItem include ActiveModel::Model attr_accessor :nickname, :email, :encrypted_password, :first_name, :family_name, :first_name_kana, :family_name_kana, :birth_day, :image, :name, :introduction, :category_id, :item_condition_id, :postage_id, :prefecture_id, :prepare_id, :price, :post_code, :prefecture_id, :city, :house_number, :building_name, :phone_number with_options presence: true do validates :nickname validates :email validates :password, format: { with: /\A[a-zA-Z0-9]+\z/, message: "Include both letters and numbers."} validates :first_name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "Full-width characters."} validates :first_name_kana, format: { with: /\A[ァ-ヶー-]+\z/, message: "Full-width katakana characters."} validates :family_name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "Full-width characters."} validates :family_name_kana, format: { with: /\A[ァ-ヶー-]+\z/, message: "Full-width katakana characters."} validates :birth_day validates :image validates :name validates :introduction validates :price validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"} validates :prefecture_id, numericality: { other_than: 0, message: "Select" } validates :city validates :house_number validates :phone_number, numericality: { only_integer: true, message: "Input only number" } validates :user validates :item end validates :price, numericality: { greater_than_or_equal_to: 300, less_than_or_equal_to: 9999999, message: "Out of setting range"} validates :price, numericality: { only_integer: true, message: "Half-width number." } with_options numericality: { other_than: 0, message: "Select" } do validates :item_condition_id validates :postage_id validates :prefecture_id validates :prepare_id validates :category_id end def save user = User.create(nickname: nickname, email: email, encrypted_password: encrypted_password, first_name: first_name, family_name: family_name, first_name_kana: first_name_kana, family_name_kana: family_name_kana, birth_day: birth_day) Item.create(image: image, name: name, introduction: introduction, category_id: category_id, item_condition_id: item_condition_id, postage_id: postage_id, prefecture_id: prefecture_id, prepare_id: prepare_id, price: price, user_id: user.id) SendingDestination.create(post_code: post_code, prefecture_id: prefecture_id, city: city, house_number: house_number, building_name: building_name, phone_number: phone_number, purchase_history_id: purchase_history.id) PurchaseHistory.create(user_id: user.id, item_id: item.id) end end
config/routes.rb Rails.application.routes.draw do devise_for :users root "items#index" resources :items do resources :purchase_histories, only: [:index, :create] end end

以下他のモデルです。

app/models/sendingdestination.rb class SendingDestination < ApplicationRecord belongs_to :purchase_history, optional: true with_options presence: true do validates :post_code, format: {with: /\A[0-9]{3}-[0-9]{4}\z/, message: "is invalid. Include hyphen(-)"} validates :prefecture_id, numericality: { other_than: 0, message: "Select" } validates :city validates :house_number validates :phone_number, numericality: { only_integer: true, message: "Input only number" } end end
app/models/purchase_history.rb class PurchaseHistory < ApplicationRecord belongs_to :user, optional: true belongs_to :item, optional: true has_one :sending_destination end

試したこと

デバッック(binding.pry)を利用して保存する情報がパラメーターに存在しているのかどうか見てみましたが、ちゃんと記録されているみたいでした。
条件分技のifの処理がtrueにならず、うまく行われていないのが原因みたいです。
optinal:trueを購入履歴のモデルファイルにつけくわてみました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

ありがとうございます。userとitemのエンティティ自体がいらなかったようです。formオブジェクトの記述時の仕方も間違っていたようで、saveメソッドの処理の中で購入履歴に関する情報を先に定義しその後に住所情報を定義するみたいでした。住所情報(sendingdestination)の定義の中に購入履歴(purchase_history)のidを入れるために、初めのpurchase_historyのインスタンス変数を作る必要があったみたいです。
あとストロングパラメーターの中に商品情報に関するidも含んでいなかったためエラーが絶えなかったようでした。
おかげさまでなんとかDB保存は成功したようです。お騒がせしてすいませんでした。ありがとうございました!

投稿2020/12/12 13:49

編集2020/12/12 13:57
murohi-08

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

def create にデバッグの跡のようなコードがありますが、実際のコードは以下の状態だとすると、

def create @item = Item.find(params[:item_id]) @user_item = UserItem.new(purchase_history_params) if @user_item.valid? @user_item.save redirect_to root_path else render action: :index end end

@user_item.valid? が false になっているんだと思います。
この valid? というメソッドは、バリデーションを通るなら true 通らないなら false を返します。

バリデーションは class UserItem にずらっと書いてありますが、
User must exist, Item must exist に該当する部分が見当たりません。
なにか心当たりはありませんか?

投稿2020/12/11 16:58

neko_daisuki

総合スコア2090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

murohi-08

2020/12/12 04:22

ご回答ありがとうございます。 userとitemのバリデーションを組んでみましたが、変化ありません。他にどこか記述がおかしい箇所はありますでしょうか?
neko_daisuki

2020/12/12 04:57

追加されたバリデーションの記述は元からあったのでしょうか? 元からあって User must exist, Item must exist と出るのなら分かるんですが、 なかったのに出るならなんかおかしいですね・・・ あとviewにnicknameやemailなどユーザーに関連する情報がないのに、 それを受け取って保存しようとしているのも不思議です。
murohi-08

2020/12/12 05:18 編集

現在Formオブジェクトパターンを使って、複数のテーブルにデータを保存するという実装をやっており、nicknameやemailなどのカラムは新規登録のviewにおいてあります。 今他のモデルにoptional :trueというUser must exist, Item must exist のエラーメッセージを消すオプションを使って消したのですが、今度は上記のエラーが発生します。 編集したのでご確認の程よろしくお願いします。
neko_daisuki

2020/12/12 05:34

このエラーは、optional: true にしたことでユーザーが空でもPurchaseHistoryのバリデーションは通ったけど、 MySQL の外部キー制約かNOT NULL制約に引っかかってます。 新規登録と同じフォームモデルを使いまわしては上手くいきません。 PurchaseHistoryを作成したいだけでも、新規登録に必要なのと同じパラメーターも必要になってしまいます。
murohi-08

2020/12/12 05:42

つまりコントローラーのパラメーターの部分の記述がおかしいということでしょうか? どの箇所を直した方がよろしいでしょうか?ご教授願います。
neko_daisuki

2020/12/12 05:53

PurchaseHistoryを作成するのに UserItem を使うのをやめたら良いんじゃないかと思います。 そうすればコントローラーの記述も変わり以下のようになるでしょう。 @p = PurchaseHistory.new(purchase_history_params) @s = SendingDestination.new(sending_destination_params) if @p.valid? && @s.valid? def purchase_history_params params.permit(purchase_historyのカラムだけ書く) end def sending_destination_params params.permit(sending_destination のカラム) end
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問