I am an experienced web developer, but new to rails. I am writing a budget application based on a double-entry accounting database. The database contains journal entries to represent transactions, and each journal entry has multiple postings. Each posting has an account and an amount.
Here are simplified versions of my models:
class Posting < ActiveRecord::Base
belongs_to :account
belongs_to :journal_entry
attr_accessible :account_id, :amount
end
class JournalEntry < ActiveRecord::Base
has_many :postings, :dependent => :destroy
attr_accessible :narrative, :posting_date, :postings_attributes
accepts_nested_attributes_for :postings, :allow_destroy => :true,
:reject_if => proc { |attrs| attrs.all? { |k, v| k == '_destroy' or v.blank? } }
end
I’ve successfully created a nested form that allows a journal entry and its list of postings to be edited together. However, most journal entries will be simple and have one credit entry and one debit entry. To make the data entry easier in this case, I want to have another form that allows the user just to specify the credit account, debit account and amount.
From my research, can see 2 ways to do this:
- Single table inheritance where SimpleJournalEntry (which extends JournalEntry)
- Using ActiveModel to make a SimpleJournalEntry model that isn’t directly attached to the database, and handle the database changes myself in the controller
The SimpleJournalEntry model would have the credit account, debit account and amount and would be used for the editing of simple records. The existing JournalEntry model would still exist to allow editing of more complex records.
Which is the ‘rails way’ to handle this kind of thing? Is there another option that I’ve not considered?
I have to disagree with railsdog on this one. I think you do have a good STI candidate. In particular, I think “let [JournalEntry] handle the details of the simple or complicated save” demonstrates that you are dealing with two separate concerns.
If your simple and complex JournalEntries have different business logic, they should be represented by two different classes. It is not hard to imagine, for example, that the complex JournalEntry might want to add validations that the simple JournalEntry does not. Or perhaps the simple JournalEntry should have fewer attr_accessible declarations than the complex JournalEntry. I would suggest:
I would handle these two classes with separate controllers and views.
On an unrelated note, the :all_blank option for #accepts_nested_attributes_for should do what your Proc does, no? From the docs: “Passing :all_blank instead of a Proc will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy.” That is,
accepts_nested_attributes_for :postings, :reject_if => :all_blank