###前提・実現したいこと
ruby on railsで、取引アカウント同士の取引記録を実装しています。
入力フォームで、ユーザーが「取引相手の口座番号」と「取引額」の2項目を入力するだけで、
取引モデル(親モデル)で1件のレコードが作成されると同時に、
1:多として関連付けを施してある入出金モデル(子モデル)に複数のレコードを自動的に作成したいと思っています。
作成するレコードは、
「出金(支払)」のレコードと
「入金(受取)」のレコードの2件です。
図にするとこんな感じです。
![
これを実現しようとしたのですが2点ほど問題が発生して困っています。
1つ目は、
undefined method `transaction_type=' for #DepositsAndWithdrawal::ActiveRecord_Associations_CollectionProxy:0x007f189cc329c0
というエラーが発生してしまって困っています。
2つ目は、入出金モデルの出金レコードの取引カラムの数値をマイナス数値として記録されないことに、
困っています。(入力フォームから渡されたパラメータの数値をマイナス数値に変換する方法がわからなくて困っています)
どうすれば、これらの問題を解消できるか教えて頂ければ幸いです。よろしくお願いします。
以下が現状のコードになります。
###現状のコード
AccountTransaction(取引)モデルは、多数のdeposits_and_withdrawals(入出金)モデルを持つという
1:多の関連付けを施してあります。
ruby
1class AccountTransaction < ApplicationRecord 2 3 belongs_to :withdrawal, class_name: 'BasicIncomeAccount', :foreign_key => 'withdrawal_account_id' 4 belongs_to :deposit, class_name: 'BasicIncomeAccount', :foreign_key => 'deposit_account_id' 5#取引モデルは、入出金モデルを多数保有している 6 has_many :deposits_and_withdrawals 7 8end
ruby
1class DepositsAndWithdrawal < ApplicationRecord 2#入出金モデルは、一つの取引モデルに保有されている 3 belongs_to :account_transaction 4 5 belongs_to :basic_income_account 6 7end 8
取引入力画面です。
app/views/account_transactions.html.erb
<%= form_for @account_transaction do |f|%> <% if @account_transaction.errors.any? %> <h3>入力内容にエラーが<%= @account_transaction.errors.count %>件あります</h3> <ul> <% @account_transaction.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> <% end %> <div class="field"> <%= f.label :送金相手の口座番号 %> <%= f.text_field :deposit_account_id %> <%# <%= f.number_field :deposit_account_id %> <%= f.label :送金額 %> <%= f.number_field :amount %> <%= f.submit"送金確認" %> </div> <div> <%= @account_transaction.errors.to_yaml %> </div> <% end %>
AccountTransactionのコントローラには、取引モデルへの記録と同時に、
入出金モデルにもレコードを作成するようにbuildメソッドを使い以下のように記述をしました。
しかし、
入力フォームで、取引を入力してsubmitボタンを押すと、
NoMethodError in AccountTransactionsController#create
undefined method `transaction_type=' for #DepositsAndWithdrawal::ActiveRecord_Associations_CollectionProxy:0x007f189cc329c0
というエラーになってしまいます。
ruby
1class AccountTransactionsController < ApplicationController 2 3 def create 4#以下5行のコードは、取引モデルに記録するためのコード 5 @account_transaction = AccountTransaction.new( 6 withdrawal_account_id: current_user.basic_income_account.id, 7 deposit_account_id: BasicIncomeAccount.find_by(account_number: params[:account_transaction][:deposit_account_id]).id, 8 amount: params[:account_transaction][:amount] 9 ) 10 ##取引モデルのレコード作成と同時に入出金モデルにも関連付けしたレコードを作成する為のコード 11 #以下5行は出金側のレコードを作成する 12 @account_transaction.deposits_and_withdrawals.build 13 @account_transaction.deposits_and_withdrawals.transaction_type = '出金' 14 @account_transaction.deposits_and_withdrawals.basic_income_account_id = current_user.basic_income_account.id 15 @account_transaction.deposits_and_withdrawals.amount = -params[:account_transaction][:amount]#ここの渡された数値をマイナス数値にしたい 16 @account_transaction.save 17 #以下5行は入金側のレコードを作成する 18 @account_transaction.deposits_and_withdrawals.build 19 @account_transaction.deposits_and_withdrawals.transaction_type = "入金" 20 @account_transaction.deposits_and_withdrawals.basic_income_account_id = BasicIncomeAccount.find_by(account_number: params[:account_transaction][:deposit_account_id]).id 21 @account_transaction.deposits_and_withdrawals.amount = params[:account_transaction][:amount] 22 @account_transaction.save 23 24###@account_transactionを保存し、保存できたらホーム画面(root_path)へ、失敗なら取引入力画面(new)へ飛ぶ。 25 if @account_transaction.save 26 redirect_to root_path 27 else 28 render "new" 29 end 30 end 31 32 def account_transaction_params 33 params.require(:account_transaction).permit(:deposit_account_id, :amount) 34 end 35end
ここまで読んでいただきありがとうございました。
もし、足りない部分を指摘して頂ければ追記します。
###補足情報(言語/FW/ツール等のバージョンなど)
Rails 5.1.3
ruby 2.4.1
###追記:アドバイスを受けて修正したコード
AccountTransactionのコントローラファイル。
ruby
1class AccountTransactionsController < ApplicationController 2 3 4 #取引を作成する 5 def new 6 @account_transaction = AccountTransaction.new 7 end 8 9 #取引を作成して記録する 10 def create 11 @account_transaction = AccountTransaction.new( 12 withdrawal_account_id: current_user.basic_income_account.id, 13 deposit_account_id: BasicIncomeAccount.find_by(account_number: params[:account_transaction][:deposit_account_id]).id, 14 amount: params[:account_transaction][:amount] 15 ) 16#####################修正中箇所############################# 17 #出金側 18 @deposits_and_withdrawal1 = DepositsAndWithdrawal.new 19 @deposits_and_withdrawal1.transaction_type = '出金' 20 @deposits_and_withdrawal1.basic_income_account_id = current_user.basic_income_account.id 21 @deposits_and_withdrawal1.amount = -1 * params[:account_transaction][:amount].to_f 22 @account_transaction.deposits_and_withdrawals << @deposits_and_withdrawal1 23 24 #入金側 25 @deposits_and_withdrawal2 = DepositsAndWithdrawal.new 26 @deposits_and_withdrawal2.transaction_type = '出金' 27 @deposits_and_withdrawal2.basic_income_account_id = BasicIncomeAccount.find_by(account_number: params[:account_transaction][:deposit_account_id]).id, 28 @deposits_and_withdrawal2.amount = params[:account_transaction][:amount] 29 @account_transaction.deposits_and_withdrawals << @deposits_and_withdrawal2 30#################修正中箇所はここまで###################### 31###@account_transactionを保存し、保存できたらホーム画面(root_path)へ、失敗なら取引入力画面(new)へ飛ぶ。 32 if @account_transaction.save 33 redirect_to root_path 34 else 35 render "new" 36 end 37 end 38 39 def account_transaction_params 40 params.require(:account_transaction).permit(:deposit_account_id, :amount) 41 end 42end
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。