usable 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa0cb884552cb07e0a3d903e528bb66cb6f111dc
4
- data.tar.gz: 8faac4e475d6c9cdc08310d7d0a79daf03fd5a6d
3
+ metadata.gz: 3820825f72ea24881e17662498e419f3aba04e78
4
+ data.tar.gz: 7c5ae702b5d0e293ba188ea4362fe8d4ece9c935
5
5
  SHA512:
6
- metadata.gz: 25c94039ef7c234eaea76ce5e44ea7bf319371ce1bf79d049c1b7c86d67e94bd173d1b762eca3d1d148b29d045844f9fbb12ab202d22fd534cc115afdc623e21
7
- data.tar.gz: 3ffd8a3aff44bcceaa14dbebc5319ce756368c300eb80bca928f5e466320f734efc00408615bee76eb538a216284ff33f95616e454ee095f3155df64424e5e6a
6
+ metadata.gz: b235afa4781dbc735133ef2635d15924bd62ce2fe5e5821f697f11c27b44f2697ffc33497cbfba6bb7e7f6cfd9e98d94e45300c1148e5aee3060ad0f0dceefdd
7
+ data.tar.gz: 246d2b78ebc8fce4b396dec9eb5368e15951f4571cb1e29de0f90402296da40ba99fe967d7d45bd724d91fc7887715a3c6abccb19f388608dd73f957b79b49b0
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ 2.2.0 (9/30/2016)
2
+ ==================
3
+
4
+ * Usable config options can now accept blocks as values, which will be lazy loaded once and memoized for future calls ([#6](https://github.com/ridiculous/usable/pull/6))
5
+
data/README.md CHANGED
@@ -8,6 +8,7 @@ module VersionMixin
8
8
  extend Usable
9
9
  config.max_versions = 25
10
10
  config.table_name = 'versions'
11
+ config.model { Audit }
11
12
 
12
13
  def save_version
13
14
  "Saving #{usables.max_versions} #{usables.table_name}"
data/bin/console CHANGED
@@ -61,6 +61,7 @@ class Example
61
61
  usable Mixin
62
62
  usable VersionMixin do
63
63
  max_versions 10
64
+ model { Model }
64
65
  end
65
66
  usable Nested::Extension
66
67
  end
data/lib/usable/config.rb CHANGED
@@ -1,24 +1,15 @@
1
+ require 'usable/config_multi'
2
+ require 'usable/config_register'
3
+
1
4
  module Usable
5
+ # Store and manage configuration settings. Keep methods to a minimum since this class relies on method_missing to read
6
+ # and write to the underlying @spec object
2
7
  class Config
3
- # = Class
4
- # Store and manage configuration settings. Keep methods to a minimum since this class relies on method_missing to read
5
- # and write to the underlying @spec object
6
- #
7
-
8
- def available_methods
9
- modules.each_with_object(Hash.new(Null.instance_method(:default_method))) do |mod, result|
10
- mod.instance_methods.each do |method_name|
11
- result[method_name] = mod.instance_method method_name
12
- end
13
- end
14
- end
8
+ include ConfigRegister
9
+ include ConfigMulti
15
10
 
16
- def add_module(mod)
17
- modules << mod
18
- end
19
-
20
- def modules
21
- @modules ||= []
11
+ def initialize
12
+ @spec = OpenStruct.new
22
13
  end
23
14
 
24
15
  def each(&block)
@@ -26,14 +17,18 @@ module Usable
26
17
  end
27
18
 
28
19
  def spec(key, value = nil)
29
- @spec ||= OpenStruct.new
30
20
  if value
31
21
  @spec[key.to_s.tr('=', '')] = value
32
22
  else
33
- @spec[key]
23
+ # Handle the case where the value may be defined with a block, in which case it's a method
24
+ @spec[key] ||= call_lazy_method(key)
34
25
  end
35
26
  end
36
27
 
28
+ def _spec
29
+ @spec
30
+ end
31
+
37
32
  def [](key)
38
33
  spec key
39
34
  end
@@ -42,19 +37,22 @@ module Usable
42
37
  spec key, val
43
38
  end
44
39
 
45
- def method_missing(method_name, *args)
46
- spec method_name, *args
47
- rescue
48
- super
40
+ def call_lazy_method(key)
41
+ @spec.public_send(key.to_s.tr('=', ''))
49
42
  end
50
43
 
51
- def respond_to_missing?(method_name, _private = false)
52
- method_name.to_s.end_with?('=') || @spec.respond_to?(method_name)
44
+ def method_missing(method_name, *args, &block)
45
+ if block
46
+ _spec.define_singleton_method(method_name) { yield }
47
+ else
48
+ spec method_name, *args
49
+ end
50
+ rescue => e
51
+ super
53
52
  end
54
53
 
55
- module Null
56
- def default_method(*, &_block)
57
- end
54
+ def respond_to_missing?(method_name, _private = false)
55
+ method_name.to_s.end_with?('=') || _spec.respond_to?(method_name)
58
56
  end
59
57
  end
60
58
  end
@@ -0,0 +1,19 @@
1
+ module Usable
2
+ module ConfigMulti
3
+ # It's important to define all block specs we need to lazy load
4
+ # Set block specs to nil values so it will fallback to calling the underlying singleton method defined by Config#method_missing
5
+ def +(other)
6
+ config = clone
7
+ specs = other._spec.to_h
8
+ specs.each { |key, val| config.spec key, val }
9
+ methods = other._spec.singleton_methods - specs.keys
10
+ methods.each do |name|
11
+ config._spec[name] = nil
12
+ config._spec.define_singleton_method(name) do
13
+ other._spec.public_method(name).call
14
+ end
15
+ end
16
+ config
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ module Usable
2
+ # Keep track of "used" modules and their "available" methods
3
+ # Mixin for Config
4
+ module ConfigRegister
5
+ def available_methods
6
+ modules.each_with_object(Hash.new(Null.instance_method(:default_method))) do |mod, result|
7
+ mod.instance_methods.each do |method_name|
8
+ result[method_name] = mod.instance_method method_name
9
+ end
10
+ end
11
+ end
12
+
13
+ def add_module(mod)
14
+ modules << mod
15
+ end
16
+
17
+ def modules
18
+ @modules ||= []
19
+ end
20
+
21
+ module Null
22
+ def default_method(*, &_block)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -18,7 +18,9 @@ module Usable
18
18
  # @description Directly include a module whose methods you want made available in +usables.available_methods+
19
19
  # Gives the module a name when including so that it shows up properly in the list of ancestors
20
20
  def call(target)
21
- override
21
+ unwanted.each do |method_name|
22
+ copy.send :remove_method, method_name
23
+ end
22
24
  if copy.name.nil?
23
25
  const_name = "#{mod_name}Used"
24
26
  target.send :remove_const, const_name if target.const_defined? const_name, false
@@ -28,25 +30,6 @@ module Usable
28
30
  target.send options[:method], copy
29
31
  end
30
32
 
31
- # @note Destructive, as it changes @copy
32
- def override
33
- unwanted.each do |method_name|
34
- copy.send :remove_method, method_name
35
- end
36
- end
37
-
38
- # @description Extends the target with the module's ClassMethod mod
39
- def use_class_methods!(target)
40
- return unless mod.const_defined? :ClassMethods
41
- target.extend mod.const_get :ClassMethods
42
- end
43
-
44
- # @description Extends the target with the module's ClassMethod mod
45
- def use_instance_methods!(target)
46
- return unless mod.const_defined? :InstanceMethods
47
- target.include mod.const_get :InstanceMethods
48
- end
49
-
50
33
  def mod_name
51
34
  if name
52
35
  name.split('::').last
@@ -1,3 +1,3 @@
1
1
  module Usable
2
- VERSION = "2.1.3".freeze
2
+ VERSION = "2.2.0".freeze
3
3
  end
data/lib/usable.rb CHANGED
@@ -61,15 +61,23 @@ module Usable
61
61
  usables[scope_name] = scope
62
62
  end
63
63
  if mod.respond_to? :usables
64
- mod.usables.each do |k, v|
65
- [scope, usables].each { |x| x.spec k, v }
66
- end
64
+ scope += mod.usables
65
+ self.usables += mod.usables
66
+ end
67
+ # any left over -options- are considered "config" settings
68
+ if options
69
+ [scope, usables].each { |x| options.each { |k, v| x[k] = v } }
70
+ end
71
+ if block_given?
72
+ [scope, usables].each { |x| x.instance_eval &block }
73
+ end
74
+ if mod.const_defined?(:InstanceMethods)
75
+ send :include, mod.const_get(:InstanceMethods)
76
+ end
77
+ if mod.const_defined?(:ClassMethods)
78
+ send :extend, mod.const_get(:ClassMethods)
67
79
  end
68
- [scope, usables].each { |x| options.each { |k, v| x[k] = v } }
69
- [scope, usables].each { |x| x.instance_eval &block } if block_given?
70
80
  ModExtender.new(mod, usable_options).call self
71
- send :include, mod.const_get(:InstanceMethods) if mod.const_defined?(:InstanceMethods)
72
- send :extend, mod.const_get(:ClassMethods) if mod.const_defined?(:ClassMethods)
73
81
  self
74
82
  end
75
83
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-28 00:00:00.000000000 Z
11
+ date: 2016-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,6 +70,7 @@ files:
70
70
  - ".ruby-gemset"
71
71
  - ".ruby-version"
72
72
  - ".travis.yml"
73
+ - CHANGELOG.md
73
74
  - Gemfile
74
75
  - LICENSE.txt
75
76
  - README.md
@@ -78,6 +79,8 @@ files:
78
79
  - bin/setup
79
80
  - lib/usable.rb
80
81
  - lib/usable/config.rb
82
+ - lib/usable/config_multi.rb
83
+ - lib/usable/config_register.rb
81
84
  - lib/usable/mod_extender.rb
82
85
  - lib/usable/version.rb
83
86
  - usable.gemspec