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.

💬 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

Published at .