usable 2.1.3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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