usable 1.2.1 → 1.3.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 +4 -4
- data/.rspec +1 -0
- data/README.md +16 -2
- data/bin/console +8 -0
- data/lib/usable/mod_extender.rb +33 -6
- data/lib/usable/version.rb +1 -1
- data/lib/usable.rb +15 -20
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e880dacf65e19267ebe16ba66d5ec85759f8e17d
|
4
|
+
data.tar.gz: 7bd498ea658d2cff0b13207a27d98df96e740442
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b4f4ce971e0f34b25190b69f67c1df97fe6e9b8ce1960d4ce10b2ec5e988f1b74187a0ef9882553be2a4aedd179220534d8e822a0f57c1d5cd068a1862e824f
|
7
|
+
data.tar.gz: fd4f4fdf322c535abea6f95d50ac02dcf3731f3aaa153b12729d2d37acd50b0ee04dca8432132c0adc083760b482e4f42cd081cd9dbc7ea4fc9684034752d017
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Usable [](http://badge.fury.io/rb/usable) [](https://travis-ci.org/ridiculous/usable) [](https://codeclimate.com/github/ridiculous/usable)
|
2
2
|
|
3
|
-
|
3
|
+
An elegant way to mount and configure your modules. Usable gives you control over which methods are included, and a simple
|
4
4
|
interface to help you call dynamic methods with confidence.
|
5
5
|
|
6
6
|
```ruby
|
@@ -31,7 +31,21 @@ model = Model.new
|
|
31
31
|
model.save_version # => "Saving up to 10 versions to custom_versions"
|
32
32
|
model.destroy_version # => NoMethodError: undefined method `destroy_version' for #<Model:...
|
33
33
|
```
|
34
|
-
`Model` now has a `#save_versions` method but no `#destroy_version` method.
|
34
|
+
`Model` now has a `#save_versions` method but no `#destroy_version` method. Usable has effectively mixed in the given module
|
35
|
+
using `include`. Ruby 2+ offers the `prepend` method, which can be used instead by specifying it as the `:method` option:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
Model.usable VersionMixin, method: :prepend
|
39
|
+
```
|
40
|
+
|
41
|
+
Usable reserves the `:only` and `:method` keys. All other keys in the given hash are defined as config settings.
|
42
|
+
If you really want to define a config on the target class with one of these names, you can simply define them in the block:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Model.usable VersionMixin, only: [:save_version] do |config|
|
46
|
+
config.only = "Will be set on `Model.usable_config.only`"
|
47
|
+
end
|
48
|
+
```
|
35
49
|
|
36
50
|
## Confidently calling methods
|
37
51
|
|
data/bin/console
CHANGED
@@ -54,11 +54,19 @@ class Model
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
module PersistenceOverride
|
58
|
+
def save
|
59
|
+
'nope'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
57
63
|
class Example
|
58
64
|
extend Usable
|
59
65
|
usable Mixin, only: [:name, :from_spec]
|
60
66
|
end
|
61
67
|
|
68
|
+
Model.usable PersistenceOverride, method: 'prepend'
|
69
|
+
|
62
70
|
require "irb"
|
63
71
|
|
64
72
|
IRB.start
|
data/lib/usable/mod_extender.rb
CHANGED
@@ -1,35 +1,62 @@
|
|
1
1
|
module Usable
|
2
2
|
class ModExtender
|
3
3
|
attr_reader :name
|
4
|
-
attr_accessor :copy, :mod, :
|
4
|
+
attr_accessor :copy, :mod, :options
|
5
5
|
|
6
|
-
def initialize(mod,
|
6
|
+
def initialize(mod, options = {})
|
7
7
|
@mod = mod
|
8
|
+
@options = options
|
9
|
+
@options[:method] ||= :include
|
8
10
|
if has_spec?
|
9
11
|
@copy = mod.const_get(:UsableSpec).dup
|
10
12
|
@name = "#{mod.name}UsableSpec"
|
11
13
|
else
|
12
|
-
@copy =
|
14
|
+
@copy = mod.dup
|
13
15
|
@name = mod.name
|
14
16
|
end
|
15
|
-
@config = config
|
16
17
|
end
|
17
18
|
|
18
|
-
# @note Destructive
|
19
19
|
def call
|
20
20
|
override
|
21
21
|
copy
|
22
22
|
end
|
23
23
|
|
24
|
+
# @note Destructive, as it changes the dup'd mod
|
24
25
|
def override
|
25
|
-
unwanted =
|
26
|
+
unwanted = options[:only] ? copy.instance_methods - Array(options[:only]) : []
|
26
27
|
unwanted.each do |method_name|
|
27
28
|
copy.send :remove_method, method_name
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
# @description Directly include a module whose methods you want made available in +usable_config.available_methods+
|
33
|
+
# Gives the module a name when including so that it shows up properly in the list of ancestors
|
34
|
+
def use!(target)
|
35
|
+
const_name = "#{mod_name}Used"
|
36
|
+
override
|
37
|
+
target.send :remove_const, const_name if target.const_defined? const_name, false
|
38
|
+
target.const_set const_name, copy
|
39
|
+
target.usable_config.modules << copy
|
40
|
+
target.send options[:method], copy
|
41
|
+
end
|
42
|
+
|
43
|
+
# @description Sends the method to the target with the original module
|
44
|
+
def use_original!(target)
|
45
|
+
return unless has_spec?
|
46
|
+
target.usable_config.modules << mod
|
47
|
+
target.send options[:method], mod
|
48
|
+
end
|
49
|
+
|
31
50
|
def has_spec?
|
32
51
|
mod.const_defined?(:UsableSpec)
|
33
52
|
end
|
53
|
+
|
54
|
+
def mod_name
|
55
|
+
if name
|
56
|
+
name.split('::').last
|
57
|
+
else
|
58
|
+
"UsableMod#{Time.now.strftime('%s')}"
|
59
|
+
end
|
60
|
+
end
|
34
61
|
end
|
35
62
|
end
|
data/lib/usable/version.rb
CHANGED
data/lib/usable.rb
CHANGED
@@ -5,48 +5,43 @@ require 'usable/mod_extender'
|
|
5
5
|
require 'usable/config'
|
6
6
|
|
7
7
|
module Usable
|
8
|
-
|
9
8
|
def usable_config
|
10
9
|
@usable_config ||= Config.new
|
11
10
|
end
|
12
11
|
attr_writer :usable_config
|
13
12
|
|
14
13
|
# @description Configures the +available_methods+ of a module using the given options or block and then includes it on
|
15
|
-
# the target class. Checks if there is a module named UsableSpec within the given mods namespace and uses the instance
|
14
|
+
# the target class. Checks if there is a module named UsableSpec within the given mods namespace and uses the instance
|
16
15
|
# methods of that as the +available_methods+
|
17
16
|
#
|
18
17
|
# @example
|
19
18
|
#
|
20
19
|
# class Example
|
21
20
|
# extend Usable
|
22
|
-
# usable
|
21
|
+
# usable Mixin, only: [:foo, :bar] do |config|
|
22
|
+
# config.baz = "Available as `Example.usable_config.baz`"
|
23
|
+
# end
|
23
24
|
# end
|
24
25
|
#
|
25
26
|
# @note Hides methods
|
26
|
-
# @note We include the primary mod when there is a UsableSpec set because any instance
|
27
|
-
# configurable and should therefore takes precedence over those defined in the UsableSpec
|
27
|
+
# @note We include the primary mod when there is a UsableSpec set because any instance methods defined on the mod are
|
28
|
+
# not configurable and should therefore takes precedence over those defined in the UsableSpec
|
29
|
+
#
|
30
|
+
# @param [Module] mod
|
31
|
+
# @param [Hash] options Customize the extension of the module as well as define config settings on the target
|
32
|
+
# @option [Array,Symbol] :only Limit which methods are copied from the module
|
33
|
+
# @option [String,Symbol] :method (:include) The method to use for including the module
|
28
34
|
# @return [ModExtender] containing the original and modified module
|
29
35
|
def usable(mod, options = {})
|
36
|
+
usable_options = { only: options.delete(:only), method: options.delete(:method) }
|
30
37
|
options.each { |k, v| usable_config.public_send "#{k}=", v }
|
31
38
|
yield usable_config if block_given?
|
32
|
-
mod_ext = ModExtender.new mod,
|
33
|
-
|
34
|
-
|
39
|
+
mod_ext = ModExtender.new mod, usable_options
|
40
|
+
mod_ext.use! self
|
41
|
+
mod_ext.use_original! self
|
35
42
|
mod_ext
|
36
43
|
end
|
37
44
|
|
38
|
-
# @description Directly include a module whose methods you want made available in +usable_config.available_methods+
|
39
|
-
# Gives the module a name when including so that it shows up properly in the list of ancestors
|
40
|
-
def usable!(mod)
|
41
|
-
mod_name = mod.name ? mod.name.split('::').last : "UsableMod#{Time.now.strftime('%s')}"
|
42
|
-
const_name = "#{mod_name}Used"
|
43
|
-
mod = mod.call if mod.respond_to? :call
|
44
|
-
remove_const const_name if const_defined? const_name, false
|
45
|
-
const_set const_name, mod
|
46
|
-
usable_config.modules << mod
|
47
|
-
send :include, mod
|
48
|
-
end
|
49
|
-
|
50
45
|
# @return [Method] bound to the given -context-
|
51
46
|
def usable_method(context, method_name)
|
52
47
|
usable_config.available_methods[method_name].bind(context)
|
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: 1.
|
4
|
+
version: 1.3.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-02-
|
11
|
+
date: 2016-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -67,6 +67,7 @@ extensions: []
|
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
69
|
- ".gitignore"
|
70
|
+
- ".rspec"
|
70
71
|
- ".ruby-gemset"
|
71
72
|
- ".ruby-version"
|
72
73
|
- ".travis.yml"
|