Say we want to model a transaction in rails between a buyer and seller which are represented as users in the system.
How do you model that in activerecord?
The short
Basically we use the user model for both the buyer and seller for manually specifying the id’s in the transaction table.
class Transaction < ActiveRecord::Base has_one :buyer, :class_name => 'User', :foreign_key => 'buyer_id' has_one :seller, :class_name => 'User', :foreign_key => 'seller_id' end
The long
Create the user
> rails g scaffold User name:string bank:string
Create the transaction
> rails g scaffold Transaction buyer_id:integer seller_id:integer amount:decimal > rake db:migrate > rails s
Update transaction to reflect buyer/seller user ids
class Transaction < ActiveRecord::Base has_one :buyer, :class_name => 'User', :foreign_key => 'buyer_id' has_one :seller, :class_name => 'User', :foreign_key => 'seller_id' end
Write a test
test/models/transaction_test.rb
require 'test_helper' class TransactionTest < ActiveSupport::TestCase test 'Create transaction' do buyer = User.new(name: 'Peter', bank: 'TD') seller = User.new(name: 'Paul', bank: 'Royal') tx = Transaction.new(buyer_id: buyer.id, seller_id: seller.id, amount: 100000.0) assert_equal(buyer.id, tx.buyer_id) assert_equal(seller.id, tx.seller_id) assert_equal(100000.0, tx.amount) end end
Should now be able to use User for multiple abstractions – a buyer and a seller.
Jan 10, 2016 @ 19:56:05
‘transaction’ is a reserved word in Rails. I learned this the hard way. See http://stackoverflow.com/q/28698986/948073 for an example of what can go wrong. As I write this I’m using the procedure at http://stackoverflow.com/a/4827163/948073 in hopes of undoing the damage. You have probably saved me at least a few hours of time by posting this, since I didn’t know whether the subclass TransactionTest was a side effect of “rails generate model” or something related to whatever kind of internal transaction testing might be the reason ‘transaction’ is a reserved word. So, thank you.
Jan 11, 2016 @ 10:14:27
Ahh I didin’t know that! Thank you. You just saved me some time too 🙂
Sep 01, 2016 @ 13:34:26
I’m struggling a bit with this. It looks good and I can get everything above to work but when I take any further steps to access the association I get some errors.
For instance trying to access @transaction.buyer in a view yields:
SQLite3::SQLException: no such column: users.buyer_id: SELECT “users”.* FROM “users” WHERE “users”.”buyer_id” = ? LIMIT ?
So it looks like the FK relationship is confused about which table it is associated with.