Home > other >  How can I call a create method of a controller in another controller in Ruby on Rails?
How can I call a create method of a controller in another controller in Ruby on Rails?

Time:06-26

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

CodePudding user response:

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/

CodePudding user response:

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
  • Related