Search code examples
ruby-on-railsruby-on-rails-4devisemodels

Properly modeling monetary transactions in Rails 4


I am making a toy application to learn Rails 4 (without just cloning a tutorial).

Users sign up (I'm using the Devise gem to take care of user authentication), and a BTC pub/prv keypair is generated, and an address is computed and displayed to the user (in a flash message), so they can top off their account. Other Users sign up, and anyone can search for anyone and a dropdown is dynamically populated with every single user, but filters down names as a User types the name of their friend/associate, whoever they want to send Bitcoin to. I am only using testnet for this idea at the moment, no real BTC (don't worry!).

Anyways, here is my idea for modeling this application:

class User < ActiveRecord::Base
  has_many :account
end

class Tx < ActiveRecord::Base
  has_one :receiver, class => "account"
  belongs_to :user, through :account
end

class Account < ActiveRecord::Base
  belongs_to :user
  has_many :tx
end

The reason why I don't like the above is because in my mind it seems that a Tx (short for transaction since transaction is a reserved word in Rails) actually belongs to two users, but my readings seem to indicate that I can't have something like this:

class User < ActiveRecord::Base
  has_many :tx
end

class Tx < ActiveRecord::Base
  has_one :receiver, class => "user"
  has_one :sender, class => "user
end

Which of these implementations is better? I appreciate any insight into this model.


Solution

  • I'd go with the second method. I went with "transfers" instead of "tx", for readability - but you can name it as you please.

    class User < ActiveRecord::Base
      has_many :transfers
      has_many :received_transfers, :class_name => "Transfer", :foreign_key => "receiver_id"
    end
    
    class Transfer < ActiveRecord::Base
      belongs_to :user # Sender
      belongs_to :receiver, :class => "User"
    end
    

    Testing it:

    >> Transfer.create(:user_id => 1, :receiver_id => 2, :amount => 4.00)
    => #<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3bd9ba668,'0.4E1',9(36)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">
    
    >> User.first.transfers
    => #<ActiveRecord::Associations::CollectionProxy [#<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3c10682f0,'0.4E1',9(18)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">]>
    
    >> User.last.received_transfers
    => #<ActiveRecord::Associations::CollectionProxy [#<Transfer id: 1, user_id: 1, receiver_id: 2, amount: #<BigDecimal:7fb3bdabace8,'0.4E1',9(18)>, created_at: "2014-09-03 04:35:47", updated_at: "2014-09-03 04:35:47">]>
    

    Happy coding!