I am looking for a rails-y method to approach the following:
Two datetime attributes in an Event :
start_at: datetime end_at: datetime
I would like to use 3 fields to access them in the form:
event_date start_time end_time
The problem is how to store the actual and virtual attributes in "sync" so that the model can be updated through the form and / or directly through start_at and end_at .
class Event < ActiveRecord::Base attr_accessible :end_at, :start_at, :start_time, :end_time, :event_date attr_accessor :start_time, :end_time, :event_date after_initialize :get_datetimes # convert db format into accessors before_validation :set_datetimes # convert accessors into db format def get_datetimes if start_at && end_at self.event_date ||= start_at.to_date.to_s(:db) # yyyy-mm-dd self.start_time ||= "#{'%02d' % start_at.hour}:#{'%02d' % start_at.min}" self.end_time ||= "#{'%02d' % end_at.hour}:#{'%02d' % end_at.min}" end end def set_datetimes self.start_at = "#{event_date} #{start_time}:00" self.end_at = "#{event_date} #{end_time}:00" end end
What works:
1.9.3p194 :004 > e = Event.create(event_date: "2012-08-29", start_time: "18:00", end_time: "21:00") => #<Event id: 3, start_at: "2012-08-30 01:00:00", end_at: "2012-08-30 04:00:00", created_at: "2012-08-22 19:51:53", updated_at: "2012-08-22 19:51:53">
Until you set the actual attributes directly ( end_at will return to end_time when checking):
1.9.3p194 :006 > e.end_at = "2012-08-30 06:00:00 UTC +00:00" => "2012-08-30 06:00:00 UTC +00:00" 1.9.3p194 :007 > e => #<Event id: 3, start_at: "2012-08-30 01:00:00", end_at: "2012-08-30 06:00:00", created_at: "2012-08-22 19:51:53", updated_at: "2012-08-22 19:51:53"> 1.9.3p194 :008 > e.save (0.1ms) BEGIN (0.4ms) UPDATE "events" SET "end_at" = '2012-08-30 04:00:00.000000', "start_at" = '2012-08-30 01:00:00.000000', "updated_at" = '2012-08-22 20:02:15.554913' WHERE "events"."id" = 3 (2.5ms) COMMIT => true 1.9.3p194 :009 > e => #<Event id: 3, start_at: "2012-08-30 01:00:00", end_at: "2012-08-30 04:00:00", created_at: "2012-08-22 19:51:53", updated_at: "2012-08-22 20:02:15"> 1.9.3p194 :010 >
My assumption is that I also need to configure the “actual” attribute settings , but I'm not sure how to do this so as not to damage the default behavior. Thoughts? Perhaps there is a more "Rails-y" "callback-y" way to handle this?