usable 2.2.1 → 3.0.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: 2f7f30e1bcf362f74f31d504c1d8dcde61186cd8
4
- data.tar.gz: c62e74cf53de5e985e17e5c6d80b7eb06cbb55a4
3
+ metadata.gz: 18d15fe43c88882ead95863b946d7ee496b37bff
4
+ data.tar.gz: 06d47996bebf7e130062441d55e5104f39635dbc
5
5
  SHA512:
6
- metadata.gz: 56fadf0636c4eefa597f4e8f4ee0b518e21bc0ef512746160131ea248742884977b1d7f80d303256ebd80658f6f2b7fe47a9c22d439aa4adf364901051f48df1
7
- data.tar.gz: 19a2ec805bb337dc7a404d2f9452812667bcac73e8742814934b91b4ae08d5017183d6c41a0a019dee4b11b17023a3a60a51c08fcc161fddde4a9170d5bc863f
6
+ metadata.gz: 8ffbe8e76c89a3f04eaf70dc4edc61aaa9e03f80cc06c567ec99146108515e1c2a594c7def908ac622d0483b6e90bb0f2380a309066e4c31a5cc2e836c341a2e
7
+ data.tar.gz: 35c77816de2bbf4a99bbd33fdc9c2754cafcc2ea3f39f0719b8b34315a3fb62cc66f885d8074df396a2b472b1cc902d76516eaca1e179ef7adc20fbd897e6c25
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ 3.0 (11/4/2016)
2
+ ===============
3
+
4
+ * Multiple mods can be given to +usable+ simultaneously
5
+ * The +usables+ method no longer accepts a block (for performance reasons)
6
+ * Fix bug in Config#method_missing that was swallowing errors
7
+ * Fix bug in scoping Instance and Class method mods to the target module
8
+
9
+ 2.2.1 (10/14/2016)
10
+ ==================
11
+
12
+ * Usable config is copied correctly when extending a usable module
13
+
1
14
  2.2.0 (9/30/2016)
2
15
  ==================
3
16
 
data/README.md CHANGED
@@ -3,12 +3,16 @@
3
3
  Usable provides an elegant way to mount and configure your modules. Class level settings can be configured on a per module basis,
4
4
  available to both the module and including class. Allows you to include only the methods you want.
5
5
 
6
+ Configure a module to be usable
6
7
  ```ruby
7
8
  module VersionMixin
8
9
  extend Usable
9
- config.max_versions = 25
10
- config.table_name = 'versions'
11
- config.model { Audit }
10
+
11
+ config do
12
+ max_versions 25
13
+ table_name 'versions'
14
+ observer { Class.new }
15
+ end
12
16
 
13
17
  def save_version
14
18
  "Saving #{usables.max_versions} #{usables.table_name}"
@@ -18,7 +22,10 @@ module VersionMixin
18
22
  "Deleting versions from #{usables.table_name}"
19
23
  end
20
24
  end
25
+ ```
21
26
 
27
+ Include the module into a class using `usable`, which will copy over any configuration options
28
+ ```ruby
22
29
  class Model
23
30
  extend Usable
24
31
 
@@ -32,9 +39,12 @@ class Model
32
39
  end
33
40
 
34
41
  model = Model.new
35
- model.save_version # => "Saving 10 versions"
36
- model.destroy_version # => NoMethodError: undefined method `destroy_version' for #<Model:...
42
+ model.save_version # => "Saving 10 versions"
43
+ model.destroy_version # => NoMethodError: undefined method `destroy_version' for #<Model:...
44
+ model.usables.max_versions # => 10
45
+ model.usables.table_name # => "version"
37
46
  ```
47
+
38
48
  `Model` now has a `#save_versions` method but no `#destroy_version` method. Usable has effectively mixed in the given module
39
49
  using `include`. Ruby 2+ offers the `prepend` method, which can be used instead by specifying it as the `:method` option:
40
50
 
@@ -42,6 +52,8 @@ using `include`. Ruby 2+ offers the `prepend` method, which can be used instead
42
52
  Model.usable VersionMixin, method: :prepend
43
53
  ```
44
54
 
55
+ A usable module can also be extended onto a class with `method: :extend`
56
+
45
57
  Usable reserves the `:only` and `:method` keys. All other keys in the given hash are defined as config settings. If you really
46
58
  want to define a config on the target class with one of these names, you can simply define them in the block:
47
59
 
@@ -114,10 +126,41 @@ Add this line to your application's Gemfile:
114
126
  gem 'usable'
115
127
  ```
116
128
 
117
- ## TODO
129
+ ## Tips and Tricks
130
+
131
+ When usable modules define the same config setting, the last one mounted takes precedence. Fortunately,
132
+ Usable also "stacks" config settings by namespacing them:
133
+
134
+ ```ruby
135
+ module Robot
136
+ extend Usable
137
+ config do
138
+ speak 'beep bop'
139
+ end
140
+ end
141
+
142
+ module Human
143
+ extend Usable
144
+ config do
145
+ speak 'Hello'
146
+ end
147
+ end
118
148
 
119
- * Support blocks for config values (e.g. `config.user { User.first }`)
149
+ class User
150
+ extend Usable
151
+ usable Human, Robot
152
+ end
153
+
154
+ User.usables.speak # => "beep bop"
155
+ User.usables.human.speak # => "Hello"
156
+ User.usables.robot.speak # => "beep bop"
157
+ ```
120
158
 
159
+ Import just a module's constants with this little trick:
160
+
161
+ ```ruby
162
+ usable ExampleMod, only: []
163
+ ```
121
164
 
122
165
  ## Development
123
166
 
data/lib/usable/config.rb CHANGED
@@ -47,7 +47,7 @@ module Usable
47
47
  else
48
48
  spec method_name, *args
49
49
  end
50
- rescue => e
50
+ rescue NoMethodError
51
51
  super
52
52
  end
53
53
 
@@ -1,3 +1,3 @@
1
1
  module Usable
2
- VERSION = "2.2.1".freeze
2
+ VERSION = "3.0.0".freeze
3
3
  end
data/lib/usable.rb CHANGED
@@ -20,19 +20,21 @@ module Usable
20
20
  end
21
21
  end
22
22
  else
23
+ # Define +config+ when added to a module
23
24
  base.instance_eval do
24
25
  def config(&block)
25
- usables(&block)
26
+ if block
27
+ usables.instance_eval &block
28
+ else
29
+ usables
30
+ end
26
31
  end unless defined? config
27
32
  end
28
33
  end
29
34
  end
30
35
 
31
- # @description Read and write configuration options
32
36
  def usables
33
37
  @usables ||= Config.new
34
- return @usables unless block_given?
35
- @usables.instance_eval &Proc.new
36
38
  end
37
39
 
38
40
  attr_writer :usables
@@ -54,30 +56,33 @@ module Usable
54
56
  # @option [Array,Symbol] :only Limit which methods are copied from the module
55
57
  # @option [String,Symbol] :method (:include) The method to use for including the module
56
58
  # @return self
57
- def usable(mod, options = {}, &block)
58
- ModExtender.new(mod, only: options.delete(:only), method: options.delete(:method)).call self
59
- # Define settings on @usables and on the scoped @usables
60
- scope = Config.new
61
- if mod.name
62
- scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase
63
- usables[scope_name] = scope
64
- end
65
- if mod.respond_to? :usables
66
- scope += mod.usables
67
- self.usables += mod.usables
68
- end
69
- # any left over -options- are considered "config" settings
70
- if options
71
- [scope, usables].each { |x| options.each { |k, v| x[k] = v } }
72
- end
73
- if block_given?
74
- [scope, usables].each { |x| x.instance_eval &block }
75
- end
76
- if mod.const_defined?(:InstanceMethods)
77
- send :include, mod.const_get(:InstanceMethods)
78
- end
79
- if mod.const_defined?(:ClassMethods)
80
- send :extend, mod.const_get(:ClassMethods)
59
+ def usable(*args, &block)
60
+ options = args.last.is_a?(Hash) ? args.pop : {}
61
+ args.each do |mod|
62
+ ModExtender.new(mod, only: options.delete(:only), method: options.delete(:method)).call self
63
+ # Define settings on @usables and on the scoped @usables
64
+ scope = Config.new
65
+ if mod.name
66
+ scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase
67
+ usables[scope_name] = scope
68
+ end
69
+ if mod.respond_to? :usables
70
+ scope += mod.usables
71
+ self.usables += mod.usables
72
+ end
73
+ # any left over -options- are considered "config" settings
74
+ if options
75
+ [scope, usables].each { |x| options.each { |k, v| x[k] = v } }
76
+ end
77
+ if block_given?
78
+ [scope, usables].each { |x| x.instance_eval &block }
79
+ end
80
+ if mod.const_defined?(:InstanceMethods, false)
81
+ send :include, mod.const_get(:InstanceMethods, false)
82
+ end
83
+ if mod.const_defined?(:ClassMethods, false)
84
+ send :extend, mod.const_get(:ClassMethods, false)
85
+ end
81
86
  end
82
87
  self
83
88
  end
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.2.1
4
+ version: 3.0.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-10-15 00:00:00.000000000 Z
11
+ date: 2016-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler