Skip to content

Instantly share code, notes, and snippets.

@jacobwalkr
Last active February 9, 2021 17:18
Show Gist options
  • Save jacobwalkr/d4c95f1d95d14bbce047041390a3086a to your computer and use it in GitHub Desktop.
Save jacobwalkr/d4c95f1d95d14bbce047041390a3086a to your computer and use it in GitHub Desktop.
ActiveRecord concern for accessing the date and time parts of a datetime attribute separately
module DateTimeSplittable
extend ActiveSupport::Concern
included do
def self.split_date_time(*attributes)
attributes.each do |attribute|
if self.type_for_attribute(attribute).type != :datetime
raise ArgumentError.new("#{attribute} is not of type datetime")
end
attr_get = attribute.to_s
attr_set = attribute.to_s + '='
date_get = attr_get + '_date'
date_set = attr_get + '_date='
time_get = attr_get + '_time'
time_set = attr_get + '_time='
define_method(date_get) do
self.instance_variable_get("@#{date_get}") || self.send(attr_get)&.to_date
end
define_method(date_set) do |value|
if value.blank?
self.send(attr_set, value)
self.instance_variable_set("@#{date_get}", value)
return value
elsif self.send(attr_get).blank?
self.send(attr_set, Time.zone.local(0)) # want time to be 0 in this case
end
if value.is_a?(String)
value = Date.parse(value)
self.instance_variable_set("@#{date_get}", value)
end
self.send(attr_set, self.send(attr_get).change(year: value&.year, month: value&.month, day: value&.day))
end
define_method(time_get) do
self.instance_variable_get("@#{time_get}") || self.send(attr_get)&.to_time
end
define_method(time_set) do |value|
if value.blank?
self.send(attr_set, value)
self.instance_variable_set("@#{time_get}", value)
return value
elsif self.send(attr_get).blank?
self.send(attr_set, Time.zone.local(0)) # want time to be 0 in this case
end
if value.is_a?(String)
value = Time.zone.parse(value)
self.instance_variable_set("@#{time_get}", value)
end
self.send(attr_set, self.send(attr_get).change(hour: value&.hour, min: value&.min))
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment