Created
June 29, 2021 02:39
-
-
Save elithecho/955120177e499b769cd7f994cb49dd39 to your computer and use it in GitHub Desktop.
Bool At Rails Lazy bugger
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 BoolAt | |
extend ActiveSupport::Concern | |
class_methods do | |
# Defines a bool_at DSL | |
# allows setting true false on a virtual attribute | |
# and maps to attr_at | |
def bool_at(*attrs) | |
attrs.each do |attr| | |
at_attribute = "#{attr}_at" | |
at_setter = "#{attr}_at=" | |
setter = "#{attr}=" | |
predicate = "#{attr}?" | |
attribute attr, :boolean, default: false | |
after_initialize do | |
self[attr] = send(attr) | |
end | |
# Changes dirty state in virtual attribute | |
define_method setter do |value| | |
super(value) | |
send(at_setter, self[attr] ? Time.current : nil) | |
end | |
define_method attr do | |
send(at_attribute).present? if respond_to?(at_attribute) | |
end | |
define_method at_setter do |value| | |
self[attr] = value.present? | |
super(value) | |
end | |
alias_method predicate, attr | |
scope attr, -> { where("#{table_name}.#{attr}_at IS NOT NULL") } | |
scope :"not_#{attr}", -> { where("#{table_name}.#{attr}_at IS NULL") } | |
scope :"order_#{attr}", -> { order("#{table_name}.#{attr}_at DESC") } | |
scope :"reverse_#{attr}", -> { order("#{table_name}.#{attr}_at ASC") } | |
end | |
end | |
end | |
end |
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
require "rails_helper" | |
class UserDummy < ApplicationRecord | |
self.table_name = "users" | |
attribute :marked_at, :datetime | |
bool_at :marked, :created | |
end | |
RSpec.describe BoolAt do | |
let(:user) { UserDummy.new } | |
describe "setter" do | |
it "sets time_at on attribute" do | |
user.marked = true | |
expect(user.marked_at).not_to be_nil | |
expect(user.marked_at).to be_a(Time) | |
end | |
it "receives form input and cancels" do | |
user.marked_at = Time.current | |
user.marked = "0" | |
expect(user.marked_at).to be_nil | |
expect(user.marked?).to be false | |
end | |
end | |
describe "predicate" do | |
context "when bool_at is nil" do | |
it { expect(user.marked?).to be false } | |
end | |
context "when bool_at is set" do | |
before { user.marked = true } | |
it { expect(user.marked?).to be true } | |
end | |
end | |
describe "alias" do | |
it "sets alias on predicate as getter" do | |
user.marked = true | |
expect(user.marked?).to be true | |
expect(user.marked_at).not_to be_nil | |
end | |
end | |
describe "scope" do | |
it "sets query scope for attribute" do | |
expect(UserDummy.respond_to?(:marked)).to be true | |
expect(UserDummy.respond_to?(:not_marked)).to be true | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment