lib/usable.rb in usable-1.4.0 vs lib/usable.rb in usable-2.0.0

- old
+ new

@@ -3,25 +3,50 @@ require 'usable/version' require 'usable/mod_extender' require 'usable/config' module Usable - def usable_config - @usable_config ||= Config.new + + # @description Define an instance level version of +usables+ + def self.extended(base) + base.class_eval do + def usables + self.class.usables + end + + def usable_method(method_name) + self.class.usable_method(self, method_name) + end + end + unless base.is_a? Class + base.instance_eval do + def config(&block) + usables(&block) + end unless defined? config + end + end end - attr_writer :usable_config + # @description Read and write configuration options + def usables + @usables ||= Config.new + return @usables unless block_given? + @usables.instance_eval &Proc.new + end + + attr_writer :usables + # @description Configures the +available_methods+ of a module using the given options or block and then includes it on # the target class. Checks if there is a module named UsableSpec within the given mods namespace and uses the instance # methods of that as the +available_methods+ # # @example # # class Example # extend Usable - # usable Mixin, only: [:foo, :bar] do |config| - # config.baz = "Available as `Example.usable_config.baz`" + # usable Mixin, only: [:foo, :bar] do + # baz "Available as `Example.usables.baz` or `Example.usables.mixin.baz`" # end # end # # @note Hides methods # @note We include the primary mod when there is a UsableSpec set because any instance methods defined on the mod are @@ -30,24 +55,33 @@ # @param [Module] mod # @param [Hash] options Customize the extension of the module as well as define config settings on the target # @option [Array,Symbol] :only Limit which methods are copied from the module # @option [String,Symbol] :method (:include) The method to use for including the module # @return [ModExtender] containing the original and modified module - def usable(mod, options = {}) + def usable(mod, options = {}, &block) usable_options = { only: options.delete(:only), method: options.delete(:method) } - if mod.respond_to? :usable_config - mod.usable_config.to_h.each { |k, v| usable_config.public_send "#{k}=", v } + # Define settings on @usables and on the scoped @usables + scope = Config.new + if mod.name + scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase + usables[scope_name] = scope end - options.each { |k, v| usable_config.public_send "#{k}=", v } - yield usable_config if block_given? + if mod.respond_to? :usables + mod.usables.each do |k, v| + [scope, usables].each { |x| x.spec k, v } + end + end + [scope, usables].each { |x| options.each { |k, v| x[k] = v } } + [scope, usables].each { |x| x.instance_eval &block } if block_given? + # Include module mod_ext = ModExtender.new mod, usable_options mod_ext.use! self mod_ext.use_original! self mod_ext.use_class_methods! self mod_ext end # @return [Method] bound to the given -context- def usable_method(context, method_name) - usable_config.available_methods[method_name].bind(context) + usables.available_methods[method_name].bind(context) end end