Last active
February 9, 2021 17:18
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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