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