Reputation: 2665
I'm working on an app that will help me track me finances. There's a model that tracks my investment accounts (e.g. 401k, etc.) and the monthly balance associated with each account. The investment_accounts model has_many balances and the balances belong_to investment_accounts.
I'd like the app to now track debt, specifically my mortgage. But I'm struggling to figure out how to best model this? I'll need to have a mortgage model that has different information that than the investment_accounts (specifically interest rate). But the mortgage model should leverage the balances table, since tracking mortgage balances is so similar to tracking investment account balances. But I'm at a loss for how to revise the balances table to make it sufficiently flexible to service both the mortgage table and the investment_account table.
I considered adding a 'type' attribute on the balances model and creating named scopes like this:
scope :investment_accounts, where(type: 'investment')
scope :mortgage, where(type: 'mortgate')
But then I realized this should lead to some weird looking ActiveRecord queries. For instances:
investment_accounts.balances.investment_accounts
and
mortgage.balances.mortgage
I take this as a code smell. Any suggestions on how to do this right?
Upvotes: 0
Views: 69
Reputation: 24815
This is the case for polymorphic association
.
class InvestmentAccount < ActiveRecord::Base
has_many :balances, as: :balanceable
end
class Mortgage < ActiveRecord::Base
has_many :balances, as: :balanceable
end
class Balance < ActiveRecord::Base
belongs_to :balanceable, polymorphic: true
end
By this your Balance will have a column balanceable
which storing the type such as "investment_account", "mortgage", and possible more.
# Usage
account = InvestmentAccount.last
account.balances
mortgage = Mortgage.last
mortgage.balances
balance = Balance.last
balance.balanceable # Will return object according to its balanceable
For more about polymorphic and its migration, check the guide: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Upvotes: 1
Reputation: 18037
Balance could just have some optional fields that are only used as needed. Or you could use STI to make Balance a super class and then subclass for each type. So you might have a MortgageBalance and an InvestmentAccountBalance class whose parent is Balance. They'd share the same table, have a type field, and allow for the model to distinguish based on its type. But I'm not sure that's necessary. You may just be able to keep it loose and use duck typing. mortgage.balances
would be Balances tailored for Mortgages and may not even need to know the difference. The relationship to the Mortgage object could create the difference. Make sense?
Upvotes: 1