The idea of a date flag is to allow the user to interact with a checkbox, but the data persisted is a date/datetime.
So you might want “user_approved_at”, so you know exactly the time/date a user clicked the checkbox, but you don’t actually want to manage it.
below is a simple_form custom input, which does what we want and utilizes bootstrap5.1 classes.
# app/inputs/date_flag_input.rb
# frozen_string_literal: true
class DateFlagInput < SimpleForm::Inputs::BooleanInput
def input(wrapper_options = {})
flag_value = object.send(attribute_name)
# date_flag magic
input_html_options[:checked] = flag_value ? (flag_value <= Time.now) : false
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
merged_input_options[:class] = [input_html_classes]
template.content_tag(:div, class: container_class_name) do
build_hidden_field_for_checkbox +
build_check_box_without_hidden_field(merged_input_options) +
@builder.label(label_target, label_text, {class: boolean_label_class})
end
end
def label_translation
if SimpleForm.translate_labels && (translated_label = translate_from_namespace(:labels))
translated_label
elsif object.class.respond_to?(:human_attribute_name)
object.class.human_attribute_name(reflection_or_attribute_name.to_s.gsub(/_at$/, ''))
else
attribute_name.to_s.gsub(/_at$/, '').humanize.titleize
end
end
def container_class_name
"form-check"
end
def label(wrapper_options)
template.label_tag(nil, ' '.html_safe)
end
def input_html_classes
'form-check-input'
end
def boolean_label_class
"form-check-label"
end
def checked_value
Time.now
end
def unchecked_value
0
end
end
and also bootstrap 5 has a cool switch
# app/inputs/date_flag_switch_input.rb
# frozen_string_literal: true
class DateFlagSwitchInput < DateFlagInput
def container_class_name
"form-check form-switch"
end
end
Then in your view, you can do
<%= f.input(:user_approved_order_at, as: :date_flag_switch) %>
and it will output a pretty checkbox.