0

I have two controllers one is Payments and one is Transactions, I need to call the create method of transactions inside the create method of payments. So that each time I create a payment a transaction is automatically created. How should I approach this?

module Api
class PaymentsController < ApplicationController
  before_action :set_payment, only: %i[ show update destroy ]

  def index
    @payments = Payment.all
    render json: @payments
  end
  def show
    render json: @payment
  end
  def create
    @payment = Payment.new(payment_params)
    if @payment.save
      render json: 'Payment Is Made sucessfully'.to_json, status: :ok
    else
      render json: @payment.errors, status: :unprocessable_entity
    end
  end
  private
    def payment_params
      params.permit(:currency, :amount, :payment_type, :payment_address)
    end
end
end
module Api
class TransactionsController < ApplicationController
  before_action :set_transaction, only: %i[show update destroy]

  def index
    @transactions = Transaction.all
    render json: @transactions
  end
  def show
    render json: @transaction
  end
  # POST /transactions
  def create
    @transaction = Transaction.new(transaction_params)
    if @transaction.save
      render json: @transaction, status: :created, location: @transaction
    else
      render json: @transaction.errors,status::unprocessable_entity
    end
  end
  private
  def transaction_params
    params.permit(:transaction_type, :bank_name, :debit, :credit, :total_amount)
  end
end
end
1
  • I suggest having a look at NestedAttributes. Commented Jun 25, 2022 at 17:56

2 Answers 2

2

First to note, MVC is just a convention or good way to organize your code.

You can simply do:

def create
  @transaction = Transaction.new(transaction_params)

  # You'll have to figure out how to get the params in here - maybe they are all derived from the transaction?
  @payment = Payment.new()

  @payment.save

  # handle payment error here too like below

  if @transaction.save
    render json: @transaction, status: :created, location: @transaction
  else
    render json: @transaction.errors,status::unprocessable_entity
  end
end 

However, this doesn't present itself well towards reusable code.

We have 2 options - put it into the model or introduce a service.

In the transaction model, we can create a function like:

class Transaction
  ...

  def self.create_with_payment(params)
    Transaction.create(params)
    Payment.create(params)

    # do whatever here to create and associate these
  end

or we can introduce a service object:

class TransactionPaymentCreator
  def call(params)
    Transaction.create(params)
    Payment.create(params)
  end
end

You can then call this in your controller:

def create
  service = TransactionPaymentCreator.new
  service.call
end

I'm leaving out a lot of detail like how to set these things up - but I hope to convey to you the general details - you have 3 options on how to make this work.

Here is a good article and resource on reading more for service objects if you decide to go that route:

https://www.honeybadger.io/blog/refactor-ruby-rails-service-object/

Sign up to request clarification or add additional context in comments.

Comments

0

My approach would be to make a callback on your Payment model:

# payment.rb

after_create :create_transaction

def create_transaction
  Transaction.create(payment_id: id) # or whatever params you need in the transaction
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.