Hi there,
I want to create a rails app to track vehicle mileage. I figure this
would be a good first project to learn how to use rails. But I’m
hitting a snag.
I want to have a model for refueling events. They’d have a date,
odometer reading, gallons, cost, etc. But the problem is that for each
event there is a number of miles elapsed since the previous event.
(This is the miles travelled) I don’t want to force the user to do
that math, I just want to enter the odometer reading at each event.
I can think of two ways to handle this, and I don’t like either. I’m
hoping to get some feedback on the “correct” way to do this.
Possibility one: Have an elapsed miles property on the event, but not
stored in the data base. Then whenever a collection of events is
loaded from the db, a helper method iterates over the events, and
calculates the correct elapsed miles for each one.
- Seems like I’d have to do this iteration a lot. And I want to be DRY
Possibility two: Store the elapsed miles in the database. When a new
event is created, attempt to find the previous event (it’ll be the one
with the highest odometer reading) and set the elapsed miles from the
current - previous odometer settings.
- Assumes I’d have to enter the events in order, and what happens when
a user edits an event somewhere in the middle, and changes the
odometer setting.
Admittedly, I’m a noob and I come from a java background, so my brain
hurts as I try to transition into the ruby/rails way of thinking. Any
suggestions will be helpful and educational.
Thanks,
John Schank
Store the elapsed miles of the last trip as well as the odometer
reading… since many cars have an elapsed miles since that little
nobbly thing was pressed AND an odometer. If they don’t enter the
elapsed mileage, find the one with the highest odometer and then do
the math in a before_save. You don’t need to enter them in any order,
just do a Trip.find(:first, :order => “odometer_reading DESC”) and
that’ll find the last one with the highest reading.
When a user updates one in the middle, get it to change the elapsed
mileage on that one, as well as all future events because they
could’ve all changed. This may be a costly procedure, however.
Thanks for the reply. I like the suggestion, what I meant about out of
order… Suppose I have a accumulated a few gas station receipts, and
I want to enter them in bulk. In such a case, the entries might not be
added in odometer order. It is the same problem as when a user makes a
mistake, then goes back and edits an entry somewhere in the middle of
the entries. If that edit changes the odometer reading. (i.e. the
first time it was entered, the reading had some transposed digits or
something) Then I would need to propagate that edit forward through
all subsequent entries.
Also, suppose the user enters both an odometer reading, and a trip
reading. But they don’t agree. (i.e. the trip was reset earlier by
mistake or similar)
It is these reasons why I lean toward not storing the trip distance.
And just calculating it. I was hoping there would be a mechanism, like
a before_filter, where I could inject my iteration and calculation
once.
If they don’t agree then there’s been a mistake made somewhere…
maybe notify them of this and still add it in? Not sure.
I did mention before you could use a before_save to do all this
calculation in your model.
ahh, right you are. I totally missed the before save. (But my
subconscious must not have missed it because I mentioned the
filter…heh must be bed time)
Is there an advantage to saving it? I mean couldn’t I do some math in
something like an “after_read” if that exists? Then my model has the
info it needs. The model should be correct. And I don’t write any
potentially conflicting data, in the case where data is entered out of
order. Also, if a user edits a previous odometer reading. Wouldn’t my
next read of the data re-calculate in the (possibly mythical)
“after_read”?
Thanks again,
John
I think there may be an after_find.