Wouldn't logic like this be better
suited for the model? Fat model,
skinny controller?
I think this is absolutely right. I despise using a controller for stuff like this. In my opinion, controllers are best used for a few things:
- Shuffling data between views and models, ala CRUD operations
- Access control (usually with before_filters)
- Support to fancy UI actions (multiple select, wizards, etc)
Of course everyone has to find their own balance, but I find "making an exception" for something like this tends to lead to exceptions everywhere. Not to mention the controller logic is harder to test.
To answer your question: you should simply define virtual attributes in your model that help you convert between start_at and a duration. Something like:
# Return the duration in seconds. Will look different if you want to use
# multiparameter assignment (which you definitely should consider)
def duration
(end_at - start_at).seconds
end
# Store the duration as an instance variable. Might need to use multiparameter
# assignment if you use a time_select() in the view.
def duration=(arg)
@duration = arg
end
before_save :set_end_at
def set_end_at
end_at = start_at + @duration.seconds
end
I'd usually set the actual attribute in a before_save to avoid any race conditions from the form assignment. You have no guarantee that start_at will get assigned before or after duration, and that can introduce bugs in your otherwise good logic.