Module: Usable
- Included in:
- Persistence
- Defined in:
- lib/usable.rb,
lib/usable/config.rb,
lib/usable/struct.rb,
lib/usable/version.rb,
lib/usable/eager_load.rb,
lib/usable/persistence.rb,
lib/usable/config_multi.rb,
lib/usable/mod_extender.rb,
lib/usable/config_register.rb
Defined Under Namespace
Modules: ConfigMulti, ConfigRegister, EagerLoad, Persistence Classes: Config, ModExtender, Railtie
Constant Summary collapse
- VERSION =
"3.10.0".freeze
Instance Attribute Summary collapse
Class Method Summary collapse
- .copy_usables(context, recipient) ⇒ Object
- .extended(base) ⇒ Object
-
.extended_constants ⇒ Object
Keep track of extended classes and modules so we can freeze all usables on boot in production environments.
- .freeze ⇒ Object
- .logger ⇒ Object
- .logger=(obj) ⇒ Object
- .Struct(attributes = {}) ⇒ Object
Instance Method Summary collapse
- #define_usable_accessors ⇒ Object
- #extended(base) ⇒ Object
- #included(base) ⇒ Object
- #inherited(base) ⇒ Object
-
#usable(*args, only: nil, except: nil, method: nil, **options, &block) ⇒ Object
Self.
-
#usable_method(context, method_name) ⇒ Method
Bound to the given -context-.
Instance Attribute Details
Class Method Details
.copy_usables(context, recipient) ⇒ Object
66 67 68 69 70 71 |
# 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) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# 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 ⇒ Object
Keep track of extended classes and modules so we can freeze all usables on boot in production environments
24 25 26 |
# File 'lib/usable.rb', line 24 def self.extended_constants @extended_constants ||= Set.new end |
.freeze ⇒ Object
28 29 30 31 32 33 34 35 36 |
# 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 ⇒ Object
9 10 11 12 13 14 15 16 17 |
# 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) ⇒ Object
19 20 21 |
# File 'lib/usable.rb', line 19 def self.logger=(obj) @logger = obj end |
.Struct(attributes = {}) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# 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 |
Instance Method Details
#define_usable_accessors ⇒ Object
91 92 93 94 95 96 97 98 |
# 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 |
#extended(base) ⇒ Object
78 79 80 81 82 83 |
# 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) ⇒ Object
85 86 87 88 89 |
# 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) ⇒ Object
73 74 75 76 |
# File 'lib/usable.rb', line 73 def inherited(base) Usable.copy_usables(self, base) super end |
#usable(*args, only: nil, except: nil, method: nil, **options, &block) ⇒ Object
Note:
Hides methods
Returns self.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/usable.rb', line 124 def usable(*args, only: nil, except: nil, method: nil, **, &block) args.each do |mod| ModExtender.new(mod, only: only, method: method, except: except).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 [scope, usables].each { |x| .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(context, method_name) ⇒ Method
Returns bound to the given -context-.
156 157 158 |
# File 'lib/usable.rb', line 156 def usable_method(context, method_name) usables.available_methods[method_name].bind(context) end |