lib/rake-commander/base/class_helpers.rb in rake-commander-0.1.4 vs lib/rake-commander/base/class_helpers.rb in rake-commander-0.2.0

- old
+ new

@@ -1,9 +1,9 @@ class RakeCommander module Base module ClassHelpers - NOT_USED = 'no_used!'.freeze + NOT_USED = :not_used! # Helper to determine if a paramter has been used # @note to effectivelly use this helper, you should initialize your target # paramters with the constant `NOT_USED` # @param val [] the value of the paramter @@ -63,19 +63,10 @@ end.join("").split(/[-_ :]+/i).compact.map do |str| str.slice(0).upcase + str.slice(1..-1) end.join("") end - # Helper to create an instance variable `name` - # @param [String, Symbol] the name of the variable - # @reutrn [String] the name of the created instance variable - def instance_variable_name(name) - str = name.to_s - str = "@#{str}" unless str.start_with?("@") - str - end - # If the class for `name` exists, it returns it. Otherwise it generates it. # @param name [String, Symbol] the name of the new class # @param inherits [Class] the parent class to _inherit_ from # @param namespace [Class, String] an existing `constant` (class or module) the new class will be namespaced on # @yield [child_class] configure the new class @@ -93,76 +84,40 @@ target_class.tap do |klass| yield(klass) if block_given? end end + # @param klasses [Arrary<Class>] the classes to sort. + # @return [Arrary<Class>] the classes in hierarchy order. + def sort_classes(*klasses) + klasses.sort do |k_1, k_2| + next -1 if k_2 < k_1 + next 1 if k_1 < k_2 + 0 + end + end + # Finds all child classes of the current class. # @param parent_class [Class] the parent class we want to find children of. # @param direct [Boolean] it will only include direct child classes. # @param scope [nil, Array] to only look for descendants among the ones in `scope`. # @return [Arrary<Class>] the child classes in hierarchy order. def descendants(parent_class: self, direct: false, scope: nil) scope ||= ObjectSpace.each_object(::Class) return [] if scope.empty? - scope.select do |klass| - klass < parent_class - end.sort do |k_1, k_2| - next -1 if k_2 < k_1 - next 1 if k_1 < k_2 - 0 - end.tap do |siblings| - if direct - siblings.reject! do |si| - siblings.any? {|s| si < s} - end - end + siblings = scope.select {|klass| klass < parent_class} + siblings = sort_classes(*siblings) + return siblings unless direct + siblings.reject! do |si| + siblings.any? {|s| si < s} end end # @param parent_class [Class] the parent class we want to find children of. # @param direct [Boolean] it will only include direct child classes. # @return [Boolean] `true` if the current class has child classes, and `false` otherwise. def descendants?(parent_class: self, direct: false) !descendants(parent_class: parent_class, direct: direct).empty? - end - - # Keeps track on class instance variables that should be inherited by child classes. - # @note - # - subclasses will inherit the value as is at that moment - # - any change afterwards will be only on the specific class (in line with class instance variables) - # - adapted from https://stackoverflow.com/a/10729812/4352306 - # TODO: this separates the logic of the method to the instance var. Think if would be possible to join them somehow. - def inheritable_class_vars(*vars) - @inheritable_class_vars ||= [:inheritable_class_vars] - @inheritable_class_vars += vars - end - - # Builds the attr_reader and attr_writer of `attrs` and registers the associated instance variable as inheritable. - def inheritable_attrs(*attrs, add_accessors: false) - if add_accessors - attrs.each do |attr| - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - class << self; attr_accessor :#{attr} end - RUBY - end - end - inheritable_class_vars(*attrs) - end - - # This callback method is called whenever a subclass of the current class is created. - # @note - # - values of the instance variables are copied as they are (no dups or clones) - # - the above means: avoid methods that change the state of the mutable object on it - # - mutating methods would reflect the changes on other classes as well - # - therefore, `freeze` will be called on the values that are inherited. - def inherited(subclass) - super.tap do - inheritable_class_vars.each do |var| - instance_var = instance_variable_name(var) - value = instance_variable_get(instance_var) - subclass.instance_variable_set(instance_var, value.freeze) - end - end end end end end