I’m working on a Rails application with some budget features…
What i want to do is allow users to create a Budget and specify a start date and an interval (like “Monthly”, “Quarterly”, “Yearly”, etc). From that i wan’t to build BudgetPeriod‘s, the first one starting at the given start date and is “interval” long. The next period starts of where the previous ends and so it should continue as time goes…
A simple solution I came up with for this was to save the intervals as string representations of Duration objects, so Monthly would be “1.month” and Quarterly “3.months”. And then use eval(interval) to calculate the periods start and end dates like this
after_create :create_periods
def create_periods
period_start = self.starting_at
while period_start <= Date.today
next_start = period_start + eval(self.interval)
period_end = next_start - 1.day
budget_periods.create(start_date: period_start, end_date: period_end)
period_start = next_start
end
end
This works real good but I get a feeling that using eval() like that and basically save code in the database is not the right way to go.
So, is this bad practise or should i rock on?
Bad! Try not to eval if you can possibly help it, it can be incredibly destructive if used improperly.
If you want to do this, it would be a better idea to dump what you’re trying to store into the database and then get it out again later:
If interval will always be dumped to and from the database like this, Rails offers a convenience method called serialize to do this automatically for you, so you’d only have to do this in your model:
Then when you do
self.interval = 3.monthsyou’re guaranteed to get just that Ruby object back out of your database, no eval necessary.