Akash Ghosh
Akash Ghosh

Reputation: 23

How can i update another model's data before save of one model

I am making a wallet application in rails. I don't know how can i update balance field in user model before insertion of a new record in transaction. When user is sending money user_id is taken from hidden field and email has to be entered of receiver and user_id,user_email,amount is stored in transaction table. How to deduct money from one record and add to another. Can i use sql update to do that?

This is user model

class User < ApplicationRecord

     devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

     has_many :transactions
end

This is user table balance in included in this field.

create_table "users", force: :cascade do |t|
 t.string   "email"    
 t.string   "encrypted_password"   
 t.string   "reset_password_token"
 t.datetime "reset_password_sent_at"
 t.datetime "remember_created_at"
 t.integer  "sign_in_count"        
 t.datetime "current_sign_in_at"
 t.datetime "last_sign_in_at"
 t.string   "current_sign_in_ip"
 t.string   "last_sign_in_ip"
 t.datetime "created_at"                         
 t.datetime "updated_at"                      
 t.string   "Firstname"            
 t.string   "Lastname"               
 t.date     "Dob"
t.integer  "Balance"

end

class Transaction < ApplicationRecord

     belongs_to :user
end

This is Transaction table. User_id is for sender and user_email is for receiver

create_table "transactions", force: :cascade do |t|
  t.integer  "user_id"
  t.string   "user_email"
  t.integer  "amount"
  t.datetime "created_at"
  t.datetime "updated_at"
end

Upvotes: 1

Views: 3246

Answers (3)

amrrbakry
amrrbakry

Reputation: 599

Fetch balances of both sender and receiver like so:

@sender = User.find_by(id: user_id)
@receiver = User.find_by(email: user_email)

And to change balances use ActiveRecord update:

if @sender.has_sufficient_balance?(amount) # make sure sender has sufficient balance first!
  @sender.update(balance: @sender.balance - amount)
  @receiver.update(balance: @receiver.balance + amount)
end

You can use a before_save callback as Alejandro Montilla suggested to do this.

Also, use decimal data type for amount and balance instead of integer

Upvotes: 0

Mayank
Mayank

Reputation: 727

You can try this code. For creating transaction from user call

current_user.transaction.new(transaction_params)

Now in model transaction.rb file

class Transaction < ApplicationRecord
  belongs_to :user
  before_save :check_and_update_balance

  def check_and_update_balance
    ## since user or sender is already there no need of sender
    receiver = User.find_by(email: user_email)
    if user.has_sufficient_balance?(amount) and receiver.present?
       user.update_attributes(balance: balance - amount)
       receiver.update_attributes(balance: balance + amount)    
    end
  end
end

HOPE this Helps !!

Upvotes: 2

Alejandro Montilla
Alejandro Montilla

Reputation: 2654

You can use before_save callback:

class User < ApplicationRecord

  before_save :do_something_transaction

  def do_something_transaction
    #here you update your transanction
  end

end

Upvotes: 2

Related Questions