module Usable
Constants
- VERSION
Attributes
usables[W]
Public Class Methods
Struct(attributes = {})
click to toggle source
# File lib/usable/struct.rb, line 2 def self.Struct(attributes = {}) Class.new do extend Usable self.usables = Usable::Config.new(attributes) define_usable_accessors attributes.keys.map(&:to_sym).each do |key| define_method(key) { @attrs[key] } define_method("#{key}=") { |new_val| @attrs[key] = new_val } end attr_accessor :attrs def initialize(attrs = {}) @attrs = usables.merge(attrs) end def [](key) @attrs[key] end def []=(key, val) @attrs[key] = val end def each(&block) @attrs.each(&block) end def to_h @attrs.dup end alias to_hash to_h def merge(other) to_h.merge!(other) end alias + merge end end
copy_usables(context, recipient)
click to toggle source
# File lib/usable.rb, line 66 def self.copy_usables(context, recipient) unless Usable.frozen? recipient.usables += context.usables Usable.extended_constants << recipient end end
extended(base)
click to toggle source
# File lib/usable.rb, line 38 def self.extended(base) if base.is_a? Class # Define an instance level version of +usables+ base.class_eval do def usables self.class.usables end def usable_method(method_name) self.class.usable_method(self, method_name) end end end unless base.respond_to?(:config) base.instance_eval do def config(&block) if block usables.instance_eval(&block) else usables end end end end extended_constants << base unless Usable.frozen? end
extended_constants()
click to toggle source
Keep track of extended classes and modules so we can freeze all usables on boot in production environments
# File lib/usable.rb, line 24 def self.extended_constants @extended_constants ||= Set.new end
freeze()
click to toggle source
Calls superclass method
# File lib/usable.rb, line 28 def self.freeze logger.debug { "freezing! #{extended_constants.to_a}" } extended_constants super # This may eager load classes, which is why we freeze ourselves first, # so the +extended+ hook doesn't try to modify @extended_constants while we're iterating over it extended_constants.each { |const| const.usables.freeze } self end
logger()
click to toggle source
# File lib/usable.rb, line 9 def self.logger @logger ||= begin require 'logger' Logger.new(STDOUT).tap do |config| config.formatter = proc { |*args| "[#{name}] #{args[0]}: #{args[-1]}\n" } config.level = Logger::ERROR end end end
logger=(obj)
click to toggle source
# File lib/usable.rb, line 19 def self.logger=(obj) @logger = obj end
new(attrs = {})
click to toggle source
# File lib/usable/struct.rb, line 14 def initialize(attrs = {}) @attrs = usables.merge(attrs) end
Public Instance Methods
[](key)
click to toggle source
# File lib/usable/struct.rb, line 18 def [](key) @attrs[key] end
[]=(key, val)
click to toggle source
# File lib/usable/struct.rb, line 22 def []=(key, val) @attrs[key] = val end
config(&block)
click to toggle source
# File lib/usable.rb, line 54 def config(&block) if block usables.instance_eval(&block) else usables end end
define_usable_accessors()
click to toggle source
# File lib/usable.rb, line 91 def define_usable_accessors usables.to_h.keys.each do |key| define_singleton_method(key) { usables.send(key) } define_singleton_method("#{key}=") { |new_val| usables.send("#{key}=", new_val) } define_method(key) { usables.send(key) } define_method("#{key}=") { |new_val| usables.send("#{key}=", new_val) } end end
each(&block)
click to toggle source
# File lib/usable/struct.rb, line 26 def each(&block) @attrs.each(&block) end
extended(base)
click to toggle source
Calls superclass method
# File lib/usable.rb, line 78 def extended(base) return if base === self base.extend(Usable) unless base.respond_to?(:usables) Usable.copy_usables(self, base) super end
included(base)
click to toggle source
Calls superclass method
# File lib/usable.rb, line 85 def included(base) base.extend(Usable) unless base.respond_to?(:usables) Usable.copy_usables(self, base) super end
inherited(base)
click to toggle source
Calls superclass method
# File lib/usable.rb, line 73 def inherited(base) Usable.copy_usables(self, base) super end
merge(other)
click to toggle source
# File lib/usable/struct.rb, line 36 def merge(other) to_h.merge!(other) end
to_h()
click to toggle source
# File lib/usable/struct.rb, line 30 def to_h @attrs.dup end
usable(*args, &block)
click to toggle source
@description Includes the given module with a set of options or block to configure it
@example
class Example extend Usable usable Mixin, only: [:foo, :bar] do baz "Available as `Example.usables.baz` or `Example.usables.mixin.baz`" end end
@note Hides methods @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 self
# File lib/usable.rb, line 123 def usable(*args, &block) options = args.last.is_a?(Hash) ? args.pop : {} only = options.delete(:only) extension_method = options.delete(:method) args.each do |mod| ModExtender.new(mod, only: only, method: extension_method).call self # Define settings on @usables and on the scoped @usables scope = Config.new # Nest the new config under a namespace based on it's name, unless it's the default name we gave if mod.name && !mod.name.include?("UsableMod") scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase usables[scope_name] = scope end if mod.respond_to? :usables scope += mod.usables self.usables += mod.usables end # any left over -options- are considered "config" settings if options [scope, usables].each { |x| options.each { |k, v| x[k] = v } } end if block_given? [scope, usables].each { |x| x.instance_eval(&block) } end if mod.const_defined?(:InstanceMethods, false) send :include, mod.const_get(:InstanceMethods, false) end if mod.const_defined?(:ClassMethods, false) send :extend, mod.const_get(:ClassMethods, false) end end self end
usable_method(method_name)
click to toggle source
# File lib/usable.rb, line 46 def usable_method(method_name) self.class.usable_method(self, method_name) end
usables()
click to toggle source
# File lib/usable.rb, line 42 def usables self.class.usables end