Skip to content

Instantly share code, notes, and snippets.

@wrburgess
Last active March 19, 2018 00:01
Show Gist options
  • Save wrburgess/9c434c1bb693fcb48219d6dd4ab00dfc to your computer and use it in GitHub Desktop.
Save wrburgess/9c434c1bb693fcb48219d6dd4ab00dfc to your computer and use it in GitHub Desktop.
Activatable concern for Rails 5
class AddActivatableFieldsToModel < ActiveRecord::Migration[5.0]
def change
add_column :users, :archived, default: false
add_column :users, :test, default: false
add_column :users, :dummy, default: false
add_index :users, :archived
end
end
# app/models/concerns/activatable.rb
module Activatable
extend ActiveSupport::Concern
included do
scope :actives, -> { where(archived: false, test: false, dummy: false) }
scope :inactives, -> { where("archived IS TRUE OR test IS TRUE OR dummy IS TRUE") }
scope :archives, -> { where(archived: true) }
scope :tests, -> { where(test: true) }
scope :dummies, -> { where(dummy: true) }
end
def active?
!archived && !test && !dummy
end
def activate!
update(archived: false, test: false, dummy: false)
end
def archive!
update(archived: true)
end
def unarchive!
update(archived: false)
end
def testify!
update(test: true)
end
def dummify!
update(dummy: true)
end
end
# spec/concerns/activatable_shared.rb
require "rails_helper"
shared_examples "activatable" do
let(:model) { described_class }
it "is active by default" do
instance_of_class = FactoryGirl.create(model.to_s.underscore.to_sym)
expect(instance_of_class.active?).to be_truthy
end
it "is not archived by default" do
instance_of_class = FactoryGirl.create(model.to_s.underscore.to_sym)
expect(instance_of_class.archived).to be_falsey
end
it "is not tested by default" do
instance_of_class = FactoryGirl.create(model.to_s.underscore.to_sym)
expect(instance_of_class.test).to be_falsey
end
it "is not dummied by default" do
instance_of_class = FactoryGirl.create(model.to_s.underscore.to_sym)
expect(instance_of_class.dummy).to be_falsey
end
describe ".activate" do
it "makes the instance active" do
instance_of_class = FactoryGirl.create(described_class.name.underscore.to_sym, :archived, :test, :dummy)
expect(instance_of_class.archived).to be_truthy
expect(instance_of_class.test).to be_truthy
expect(instance_of_class.dummy).to be_truthy
instance_of_class.activate!
expect(instance_of_class.archived).to be_falsey
expect(instance_of_class.test).to be_falsey
expect(instance_of_class.dummy).to be_falsey
end
end
describe ".archive!" do
it "makes the instance archived" do
instance_of_class = FactoryGirl.create(described_class.name.underscore.to_sym, archived: false)
expect(instance_of_class.archived).to be_falsey
instance_of_class.archive!
expect(instance_of_class.archived).to be_truthy
end
end
describe ".unarchive!" do
it "makes the instance unarchived" do
instance_of_class = FactoryGirl.create(described_class.name.underscore.to_sym, :archived)
expect(instance_of_class.archived).to be_truthy
instance_of_class.unarchive!
expect(instance_of_class.archived).to be_falsey
end
end
describe ".testify!" do
it "makes the instance in a state of test" do
instance_of_class = FactoryGirl.create(described_class.name.underscore.to_sym)
expect(instance_of_class.test).to be_falsey
instance_of_class.testify!
expect(instance_of_class.test).to be_truthy
end
end
describe ".dummify!" do
it "makes the instance dummied" do
instance_of_class = FactoryGirl.create(described_class.name.underscore.to_sym)
expect(instance_of_class.dummy).to be_falsey
instance_of_class.dummify!
expect(instance_of_class.dummy).to be_truthy
end
end
describe ".actives" do
it "only selects instances where archived and test is false" do
FactoryGirl.create(described_class.name.underscore.to_sym, :archived, :test)
FactoryGirl.create(described_class.name.underscore.to_sym, :archived)
FactoryGirl.create(described_class.name.underscore.to_sym, :test)
FactoryGirl.create(described_class.name.underscore.to_sym, :dummy)
FactoryGirl.create(described_class.name.underscore.to_sym, test: false, archived: false, dummy: false)
expect(described_class.count).to eq 5
expect(described_class.actives.count).to eq 1
end
end
describe ".inactives" do
it "only selects instances where archived and test is false" do
FactoryGirl.create(described_class.name.underscore.to_sym, :archived)
FactoryGirl.create(described_class.name.underscore.to_sym, :test)
FactoryGirl.create(described_class.name.underscore.to_sym, :dummy)
FactoryGirl.create(described_class.name.underscore.to_sym, archived: false, test: false, dummy: false)
expect(described_class.count).to eq 4
expect(described_class.inactives.count).to eq 3
end
end
describe ".archives" do
it "only selects instances where archived is false" do
FactoryGirl.create(described_class.name.underscore.to_sym, :archived)
FactoryGirl.create(described_class.name.underscore.to_sym, :archived)
FactoryGirl.create(described_class.name.underscore.to_sym, archived: false)
expect(described_class.count).to eq 3
expect(described_class.archives.count).to eq 2
end
end
describe ".tests" do
it "only selects instances where test is false" do
FactoryGirl.create(described_class.name.underscore.to_sym, :test)
FactoryGirl.create(described_class.name.underscore.to_sym, :test)
FactoryGirl.create(described_class.name.underscore.to_sym, test: false)
expect(described_class.count).to eq 3
expect(described_class.tests.count).to eq 2
end
end
describe ".dummies" do
it "only selects instances where dummy is true" do
FactoryGirl.create(described_class.name.underscore.to_sym, :dummy)
FactoryGirl.create(described_class.name.underscore.to_sym, :dummy)
FactoryGirl.create(described_class.name.underscore.to_sym, dummy: false)
expect(described_class.count).to eq 3
expect(described_class.dummies.count).to eq 2
end
end
end
# app/models/user.rb
class User < ActiveRecord::Base
include Activatable
...
end
# spec/users_spec.rb
require "rails_helper"
require "concerns/activatable_shared"
describe User, type: :model do
it_behaves_like "activatable"
...
end
# spec/factories/users.rb
FactoryGirl.define do
factory :user do
...
trait :archived do
archived { true }
end
trait :test do
test { true }
end
trait :dummy do
dummy { true }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment