Last active
February 7, 2017 19:48
-
-
Save markburns/2c6d7ec0382fc46a2dfac492d855b8d4 to your computer and use it in GitHub Desktop.
Print out /fails tests if class instance variables defined in your application code
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
# Example sets some state | |
class SomeObject | |
def self.asdf | |
@a = 1 | |
end | |
end | |
SomeObject.asdf | |
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 "pathname" | |
module EnemyOfTheState | |
class << self | |
attr_accessor :application_directories | |
end | |
module ApplicationFolders | |
extend self | |
def exclude?(method) | |
file, _ = method.source_location | |
return true unless file | |
!included_in?(expand_path(file), EnemyOfTheState.application_directories) | |
end | |
private | |
def expand_path(f) | |
Pathname.new(f).expand_path | |
end | |
SEPARATOR = "/" | |
def included_in?(p1, paths) | |
paths.any? do |p2| | |
common = common_parent(p1, p2) | |
common.to_s.length >= p2.to_s.length | |
end | |
end | |
def common_parent(path_a, path_b) | |
dirs = [ | |
Pathname.new(path_a.to_s).expand_path, | |
Pathname.new(path_b.to_s).expand_path, | |
] | |
dir1, dir2 = dirs.sort.map { |dir| dir.to_s.split(SEPARATOR) } | |
append_trailing_slash!(path_from(dir1, dir2, path_a, path_b).to_s) | |
end | |
def path_from(dir1, dir2, path_a, path_b) | |
common_path = common_path(dir1, dir2) | |
common_path, path_a, path_b = append_trailing_slashes!(common_path, path_a, path_b) | |
Pathname.new(common_path) if valid_length?(common_path, path_a, path_b) | |
end | |
def valid_length?(common_path, path_a, path_b) | |
l = common_path.to_s.length | |
(l <= path_a.to_s.length) || (l <= path_b.to_s.length) | |
end | |
def common_path(dir1, dir2) | |
dir1. | |
zip(dir2). | |
take_while { |dn1, dn2| dn1 == dn2 }. | |
map(&:first). | |
join(SEPARATOR) | |
end | |
def append_trailing_slash!(path) | |
path = path.to_s | |
if Pathname.new(path).directory? | |
path += SEPARATOR if path && path.to_s[-1] != SEPARATOR | |
end | |
path | |
end | |
def append_trailing_slashes!(*paths) | |
paths.map do |path| | |
append_trailing_slash!(path) | |
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 "set" | |
require_relative "application_folders" | |
module EnemyOfTheState | |
class << self | |
def display | |
each_class_instance_variable { |s| puts(s) } | |
end | |
def fail | |
each_class_instance_variable { |s| Kernel.fail(s) } | |
end | |
private | |
def each_class_instance_variable(&block) | |
set = Set.new | |
application_klasses do |k| | |
next if k == set || set.include?(k) | |
set.add(k) | |
variables_in(k, &block) | |
end | |
end | |
def application_klasses | |
ObjectSpace.each_object.lazy do |o| | |
klass = o.is_a?(Module) ? o : o.class rescue next | |
yield klass | |
end | |
end | |
def variables_in(klass, &block) | |
return if ignore?(klass) | |
klass.instance_variables.each do |iv| | |
val = klass.instance_eval(iv.to_s) | |
unless val.nil? | |
yield "non-nil class variable found:\n #{klass} #{iv}: #{val.inspect}" | |
end | |
end | |
end | |
def ignore?(klass) | |
methods = | |
klass.methods.map{|m| klass.method(m)} + | |
klass.instance_methods.map{|m| klass.instance_method(m) } | |
methods.all? do |m| | |
EnemyOfTheState::ApplicationFolders.exclude?(m) | |
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_relative "app/example_code" | |
require_relative "enemy_of_the_state" | |
EnemyOfTheState.application_directories = [File.expand_path("./app")] | |
EnemyOfTheState.display | |
# OR | |
# EnemyOfTheState.fail |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment