If you want maintainable, loosely coupled classes, you must mind what they know about one another.
For example, you don’t want one Active Record model to know a lot about the schema of another.
Instead of this:
1 2 3 4
You might use Active Record’s
merge and do something like:
1 2 3 4
1 2 3
We’re still coupled, of course, but to a higher and more stable abstraction.
For more complex SQL,
merge won’t cut it.
Today, I extracted columns like
contracts.emailed_at to a separate
Now there are
Event records which belong to a record (invoice or contract) and have an event name and a timestamp.
So a posted invoice may be represented by an
Event record with these attributes:
Now, if you want a scope/method like
Invoice.unposted (and perhaps
Contract.not_emailed), how would you go about it?
You’ll need a join that involves
You could put the join SQL in
Invoice, but then it would know a lot about the
events table. And you’d have to duplicate much of that SQL if
Contract adds a similar method.
Instead, you can simply have
Event own that SQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Event needs to know is that its record has a table name, a primary key and a class name, as any Active Record model will. These are fairly stable assumptions.