class Transaction < ApplicationRecord belongs_to :user # sub_types: buy_credits, spend_credits, add_free_credits # columns: credit_change end class Add_free_credits < Transaction has_one :admin_user # if added manually by the admin as free credit; nil if added by the system for signup # columns: credit_change (inherited from transaction, values positive), type ("sign_up_bonus", "goodwill") end class Purchase_credits < Transaction has_one :payment # to be added later # columns: credit_change (inherited from transaction, values positive), currency, price, amount end class Spend_credits < Transaction belongs_to :site_action # the action the user is charged for (dummy name) # columns: credit_change (inherited from transaction, values negative) end class User ... def credits_balance # or self.credits_balance ?? :) @user.transactions.sum(:amount) end # Thanks to Casey Provost, https://gorails.com/forum/how-do-i-create-a-virtual-balance-model-in-rails end
class AccountEntry < ApplicationRecord belongs_to :user belongs_to :reason, optional: true, polymorphic: true validates_numericality_of :change end Account = Struct.new(:user) do def balance user.account_entries.sum(:change) end end class User < ApplicationRecord has_many :account_entries has_many :sales def account Account.new(self) end end class Sale < ApplicationRecord belongs_to :user has_one :account_entry, required: true, as: :reason, dependent: :nullify before_create :build_associations validates_numericality_of :price, :credits, greater_than: 0 private def build_associations account_entry || build_account_entry(user: user, change: credits) end end
current_user.sales.create!(price: 2000, credits: 20)
Balance: <%= current_user.account.balance %>
Join 24,647+ developers who get early access to new screencasts, articles, guides, updates, and more.