Skip to content

Instantly share code, notes, and snippets.

@jhubert
Last active February 26, 2017 22:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhubert/1c91cd21264524dde7e07b13832233a2 to your computer and use it in GitHub Desktop.
Save jhubert/1c91cd21264524dde7e07b13832233a2 to your computer and use it in GitHub Desktop.
The after code for my article on Real World Refactoring
# Disable users who have had no activity in the last 14 days
class DisableInactiveUsersJob
include Sidekiq::Worker
def perform
users_with_no_activity_since(14.days.ago).pluck(:id).each do |user_id|
DisableUser.call(user_id)
end
end
private
def users_with_no_activity_since(time)
# fairly complicated query for figuring out if users have had activity
# omitting for simplicity
end
end
require 'test_helper'
class DisableInactiveUsersJobTest < ActiveSupport::TestCase
test "should disable all enabled users who have not had any activity" do
DisableInactiveUsers.new.perform
User.all.each do |user|
assert_predicate user, :disabled?
assert Activity.where(target: user, activity: 'user:disable').exists?
end
end
test "should not disable users who are already disabled" do
melissa = users(:melissa)
melissa.disable!
DisableInactiveUsers.new.perform
assert_predicate melissa, :disabled?
refute Activity.where(target: melissa, activity: 'user:disable').exists?
end
test "should not disable a user that has had activity within 14 days" do
melissa = users(:melissa)
Activity.create(activity: 'session:create', user: melissa, created_at: 13.days.ago)
DisableInactiveUsers.new.perform
melissa.reload
assert_predicate melissa, :enabled?
refute Activity.where(target: melissa, activity: 'user:disable').exists?
end
test "should disable a user that has had activity more than 14 days ago" do
melissa = users(:melissa)
Activity.create(activity: 'session:create', user: melissa, created_at: 15.days.ago)
DisableInactiveUsers.new.perform
melissa.reload
assert_predicate melissa, :disabled?
assert Activity.where(target: melissa, activity: 'user:disable').exists?
end
end
# Disable users who have email addresses that are bouncing
class DisableRejectedEmailsJob
include Sidekiq::Worker
def perform
User.enabled.where(email: rejected_emails).pluck(:id).each do |user_id|
DisableUser.call(user_id)
end
end
private
# Returns an array of email addresses
def rejected_emails
# Logic for pulling recently bounced email address from our mail server
end
end
# Give an active record model the ability to be enabled / disabled
# based on the timestamp value of a column
module Disableable
extend ActiveSupport::Concern
included do
scope :enabled, ->(time = Time.zone.now) { where("disabled_at IS NULL OR disabled_at > ?", time) }
scope :disabled, ->(time = Time.zone.now) { where("disabled_at < ?", time) }
end
def disable(time = Time.zone.now)
set_disabled_at_value(time)
end
def disable!(time = Time.zone.now)
update_disabled_at_value(time)
end
def enable
set_disabled_at_value(nil)
end
def enable!
update_disabled_at_value(nil)
end
def enabled?(time = Time.zone.now)
!disabled?(time)
end
def disabled?(time = Time.zone.now)
disabled_at && disabled_at <= time
end
private
def set_disabled_at_value(value) # rubocop:disable Style/AccessorMethodName
self.disabled_at = value
end
def update_disabled_at_value(value)
update_attribute(:disabled_at, value)
end
end
# Disable or enable a User by their id
class Users::DisablementsController < ApplicationController
before_action :load_user, only: [:create, :destroy]
def create
DisableUser.call(@user.id)
redirect_to user_path(@user), notice: I18n.t('user.disablements.create_notice')
end
def destroy
EnableUser.call(@user.id)
redirect_to user_path(@user), notice: I18n.t('user.disablements.destroy_notice')
end
private
def load_user
@user = User.find(params[:user_id])
end
end
require 'test_helper'
class Users::DisablementsControllerTest < ActionController::TestCase
include AuthenticatedAsAdmin
test "should enable the intended user" do
user = users(:melissa)
user.disable!
delete :destroy, user_id: user.id
user.reload
assert_predicate user, :enabled?
assert Activity.where(target: user, activity: 'user:enable').exists?
end
test "should disable the intended user" do
user = users(:melissa)
post :create, user_id: user.id
user.reload
assert_predicate user, :disabled?
assert Activity.where(target: user, activity: 'user:disable').exists?
end
# ... more tests for redirection, error messages, etc...
end
class User < ActiveRecord::Base
include Disableable
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment