Simplifying timestamp toggles in Rails
I often use timestamps, like completed_at as a boolean flag. It offers just a bit more (meta) data than a real boolean.
But of course on the UI you want to show a checkbox that a user can toggle instead of a datetime field.
I have done this often enough, that I created a simple concern that I use throughout my apps. Given above completed_at example, it gives you an API like:
@resource.completed?
@resource.complete!
@resource.complete=
So in your form, you can simply use form.check_box :completed and you’re off.
The concern is simple enough:
# lib/boolean_attributes.rb
module BooleanAttribute
extend ActiveSupport::Concern
class_methods do
def boolean_attribute(*fields)
fields.each do |field|
column = :"#{field}_at"
define_method(field) { public_send(column).present? }
define_method("#{field}?") { public_send(column).present? }
define_method("#{field}=") do |value|
public_send("#{column}=", ActiveModel::Type::Boolean.new.cast(value) ? Time.current : nil)
end
define_method("#{field}!") { update!("#{column}": Time.current) }
end
end
end
end
In your model use it like this:
class Task < ApplicationRecord
include BooleanAttributes
boolean_attribute :completed
# …
end
It is just that little concerns that make your life a bit easier.
Want to read me more?
-
Nested forms without `accepts_nested_attributes_for` in Rails
Build nested forms in Rails without accepts_nested_attributes_for. Use separate forms with auto-save and Turbo Streams for a simpler solution. -
Better Inline Validation for Rails Forms (with ViewComponent or partials)
Rails has great features in place for form validations. But the UX can be improved. Provide immediate and contextual feedback by moving form validations closer to the input fields. -
Inline editing with custom elements in Rails
Learn how to build an inline editing feature using custom elements in Rails. A clean, framework-agnostic approach to editable content with just HTML and JavaScript.
Over to you…
What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!
Comments are powered by Chirp Form
{{comment}}