Skip to content

Instantly share code, notes, and snippets.

@cpruitt
Last active May 14, 2019 19:38
Show Gist options
  • Select an option

  • Save cpruitt/63cd9063953f4ba46bd642c69babd2c1 to your computer and use it in GitHub Desktop.

Select an option

Save cpruitt/63cd9063953f4ba46bd642c69babd2c1 to your computer and use it in GitHub Desktop.
# Including this module should let us check an instance to see if a particular
# method is redundant and can be removed. Redundant methods return the same result
# as the same method defined by a superclass or inherited module
module RedundancyChecker
def check_redundant_method(meth)
result = if self.class.method_defined?(meth, false)
[{class_name: self.class, result: send(meth)}]
else
[]
end
ancestor_list = self.class.ancestors.tap(&:shift)
result = ancestor_list.inject(result) { |result, klass|
result << if klass.method_defined?(meth, false)
{class_name: klass, result: klass.instance_method(meth).bind(self).call }
else
nil
end
}.compact
self_result = self.send(meth)
redundant = result.take_while { |itm| itm[:result] == self_result }
redundant.collect {|h| h[:class_name]}.tap(&:pop)
end
end
# Set up a bunch of classes for inheritance examples.
class AppController
include RedundancyChecker
def likes_tacos
return true
end
end
class CleanController < AppController
end
class OverrideController < AppController
def likes_tacos
return false
end
end
class ResetController < OverrideController
def likes_tacos
return true
end
end
class ResetNoChangeController < OverrideController
def likes_tacos
return false
end
end
module MixinOverride
def likes_tacos
return false
end
end
class MixinOverrideController < AppController
include MixinOverride
end
class ResetMixinController < MixinOverrideController
def likes_tacos
return true
end
end
class InheritFromHasMixinController < MixinOverrideController
def likes_tacos
return true
end
end
class InheritOtherFromHasMixinController < MixinOverrideController
def likes_tacos
return false
end
end
module MixinReset
def likes_tacos
return true
end
end
class MixinResetMixinController < MixinOverrideController
include MixinReset
end
class OverrideMixinResetMixinController < MixinResetMixinController
include MixinReset
def likes_tacos
return false
end
end
class DoesSomethingController < OverrideMixinResetMixinController
def likes_tacos
return true
end
end
class DoesSomethingElseController < DoesSomethingController
def likes_tacos
return false
end
end
class MoreDoesSomethingController < DoesSomethingElseController
def likes_tacos
return false
end
end
class DoesNothingController < MoreDoesSomethingController
end
class MoreDoesNothingController < DoesNothingController
end
class DeepInheritController < MoreDoesNothingController
include MixinReset
def likes_tacos
return false
end
end
# Loop through all our example classes to see if we're redundantly liking tacos.
[
AppController,
CleanController,
OverrideController,
ResetController,
ResetNoChangeController,
MixinOverrideController,
ResetMixinController,
InheritFromHasMixinController,
InheritOtherFromHasMixinController,
MixinResetMixinController,
OverrideMixinResetMixinController,
DoesSomethingController,
DoesSomethingElseController,
MoreDoesSomethingController,
DoesNothingController,
MoreDoesNothingController,
DeepInheritController,
].each do |klass|
puts "Checking #{klass} for redundant '#likes_tacos' definition"
instance = klass.new
redundants = instance.check_redundant_method(:likes_tacos)
if redundants.empty?
puts "Looks good. Carry on."
else
puts "These classes / modules have redundent method defitions."
puts "Removing them should have no impact on #{klass}:"
puts redundants.collect{ |a| "- #{a}\n"}
end
puts "----------\n\n"
end
puts "Done. Godspeed."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment