usable 2.2.1 → 3.0.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: 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