usable 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -11
- data/bin/console +21 -7
- data/lib/usable/config.rb +43 -11
- data/lib/usable/mod_extender.rb +3 -3
- data/lib/usable/version.rb +1 -1
- data/lib/usable.rb +45 -11
- data/usable.gemspec +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 248031af23fb6b13a611f3ad52aed2b485e13042
|
4
|
+
data.tar.gz: 7d43e66f04750393514a83e5cf6af8950aecd242
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f33b9468b3368318c1eb79d692e168a05de74378307e8c8006c162511f2d6636ebf9f0f186c16ea85f08e63e2217212e110a7edc0328069d9c3667c40ffb7201
|
7
|
+
data.tar.gz: ca0191741f597b8c6c948135cc121c906a36ea6586e5d1a3aea6ac36d3a6b645162eace8e908675788be19cca9d895135b646be6504ea5022494e7cac1f93296
|
data/README.md
CHANGED
@@ -1,29 +1,33 @@
|
|
1
1
|
# Usable [![Gem Version](https://badge.fury.io/rb/usable.svg)](http://badge.fury.io/rb/usable) [![Build Status](https://travis-ci.org/ridiculous/usable.svg)](https://travis-ci.org/ridiculous/usable) [![Code Climate](https://codeclimate.com/github/ridiculous/usable/badges/gpa.svg)](https://codeclimate.com/github/ridiculous/usable)
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
Usable provides an elegant way to mount and configure your modules. Class level settings can be configured on a per module basis,
|
4
|
+
available to both the module and including class. Allows you to include only the methods you want.
|
5
5
|
|
6
6
|
```ruby
|
7
7
|
module VersionMixin
|
8
|
+
extend Usable
|
9
|
+
usables[:max_versions] = 25
|
10
|
+
usables[:table_name] = 'versions'
|
11
|
+
|
8
12
|
def save_version
|
9
|
-
"Saving up to #{
|
13
|
+
"Saving up to #{usables.max_versions} versions to #{usables.table_name}"
|
10
14
|
end
|
11
15
|
|
12
16
|
def destroy_version
|
13
|
-
"Deleting versions from #{
|
17
|
+
"Deleting versions from #{usables.table_name}"
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
class Model
|
18
22
|
extend Usable
|
19
23
|
|
20
|
-
usable VersionMixin, only: :save_version do
|
21
|
-
|
22
|
-
|
24
|
+
usable VersionMixin, only: :save_version do
|
25
|
+
max_versions 10
|
26
|
+
table_name 'custom_versions'
|
23
27
|
end
|
24
28
|
|
25
29
|
def save
|
26
|
-
|
30
|
+
usable_method(:save_version).call
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
@@ -38,8 +42,8 @@ using `include`. Ruby 2+ offers the `prepend` method, which can be used instead
|
|
38
42
|
Model.usable VersionMixin, method: :prepend
|
39
43
|
```
|
40
44
|
|
41
|
-
Usable reserves the `:only` and `:method` keys. All other keys in the given hash are defined as config settings.
|
42
|
-
|
45
|
+
Usable reserves the `:only` and `:method` keys. All other keys in the given hash are defined as config settings. If you really
|
46
|
+
want to define a config on the target class with one of these names, you can simply define them in the block:
|
43
47
|
|
44
48
|
```ruby
|
45
49
|
Model.usable VersionMixin, only: [:save_version] do |config|
|
@@ -50,13 +54,14 @@ end
|
|
50
54
|
## Confidently calling methods
|
51
55
|
|
52
56
|
We should all be writing [confident code](http://www.confidentruby.com/), which is why you might want to call configurable
|
53
|
-
methods through the `usable_method` class
|
57
|
+
methods through the `usable_method` class and instance method. Methods passed in with the `:only` option
|
54
58
|
will _always_ return `nil` when called. Thus, the confidence.
|
55
59
|
|
56
60
|
Here's the same example as above, rewritten to call methods through the Usable interface:
|
57
61
|
|
58
62
|
```ruby
|
59
63
|
Model.usable_method(model, :save_version).call # => "Saving up to 10 versions to custom_versions"
|
64
|
+
model.usable_method(:save_version).call # => "Saving up to 10 versions to custom_versions"
|
60
65
|
Model.usable_method(model, :destroy_version).call # => nil
|
61
66
|
```
|
62
67
|
|
data/bin/console
CHANGED
@@ -12,15 +12,18 @@ require "usable"
|
|
12
12
|
|
13
13
|
module VersionMixin
|
14
14
|
def save_version
|
15
|
-
"Saving up to #{
|
15
|
+
"Saving up to #{usables.max_versions} versions to #{usables.table_name}"
|
16
16
|
end
|
17
17
|
|
18
18
|
def destroy_version
|
19
|
-
"Deleting versions from #{
|
19
|
+
"Deleting versions from #{usables.table_name}"
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
module Mixin
|
24
|
+
extend Usable
|
25
|
+
usables[:max_versions] = 20
|
26
|
+
|
24
27
|
def name
|
25
28
|
"defined by Mixin"
|
26
29
|
end
|
@@ -44,13 +47,13 @@ end
|
|
44
47
|
class Model
|
45
48
|
extend Usable
|
46
49
|
|
47
|
-
usable VersionMixin, only: :save_version do
|
48
|
-
|
49
|
-
|
50
|
+
usable VersionMixin, only: :save_version do
|
51
|
+
max_versions 10
|
52
|
+
table_name 'custom_versions'
|
50
53
|
end
|
51
54
|
|
52
55
|
def save
|
53
|
-
|
56
|
+
usable_method(:save_version).call
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -60,10 +63,21 @@ module PersistenceOverride
|
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
66
|
+
module Nested
|
67
|
+
module Extension
|
68
|
+
def go
|
69
|
+
'going'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
63
74
|
class Example
|
64
75
|
extend Usable
|
65
76
|
usable Mixin
|
66
|
-
usable VersionMixin
|
77
|
+
usable VersionMixin do
|
78
|
+
max_versions 10
|
79
|
+
end
|
80
|
+
usable Nested::Extension
|
67
81
|
end
|
68
82
|
|
69
83
|
Model.usable PersistenceOverride, method: 'prepend'
|
data/lib/usable/config.rb
CHANGED
@@ -1,27 +1,59 @@
|
|
1
1
|
module Usable
|
2
|
-
class Config
|
3
|
-
|
4
|
-
|
2
|
+
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
|
5
14
|
end
|
6
15
|
|
7
16
|
def add_module(mod)
|
8
17
|
modules << mod
|
9
18
|
end
|
10
19
|
|
11
|
-
def
|
12
|
-
modules
|
13
|
-
|
14
|
-
|
15
|
-
|
20
|
+
def modules
|
21
|
+
@modules ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@spec.to_h.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def spec(key, value = nil)
|
29
|
+
@spec ||= OpenStruct.new
|
30
|
+
if value
|
31
|
+
@spec[key.to_s.tr('=', '')] = value
|
32
|
+
else
|
33
|
+
@spec[key]
|
16
34
|
end
|
17
35
|
end
|
18
36
|
|
19
|
-
def
|
20
|
-
|
37
|
+
def [](key)
|
38
|
+
spec key
|
39
|
+
end
|
40
|
+
|
41
|
+
def []=(key, val)
|
42
|
+
spec key, val
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method_name, *args)
|
46
|
+
spec method_name, *args
|
47
|
+
rescue
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def respond_to_missing?(method_name, _private = false)
|
52
|
+
method_name.to_s.end_with?('=') || spec.respond_to?(method_name)
|
21
53
|
end
|
22
54
|
|
23
55
|
module Null
|
24
|
-
def default_method(*, &
|
56
|
+
def default_method(*, &_block)
|
25
57
|
end
|
26
58
|
end
|
27
59
|
end
|
data/lib/usable/mod_extender.rb
CHANGED
@@ -30,7 +30,7 @@ module Usable
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
# @description Directly include a module whose methods you want made available in +
|
33
|
+
# @description Directly include a module whose methods you want made available in +usables.available_methods+
|
34
34
|
# Gives the module a name when including so that it shows up properly in the list of ancestors
|
35
35
|
def use!(target)
|
36
36
|
override
|
@@ -39,14 +39,14 @@ module Usable
|
|
39
39
|
target.send :remove_const, const_name if target.const_defined? const_name, false
|
40
40
|
target.const_set const_name, copy
|
41
41
|
end
|
42
|
-
target.
|
42
|
+
target.usables.add_module copy
|
43
43
|
target.send options[:method], copy
|
44
44
|
end
|
45
45
|
|
46
46
|
# @description Includes or prepends the original module onto the target
|
47
47
|
def use_original!(target)
|
48
48
|
return unless has_spec?
|
49
|
-
target.
|
49
|
+
target.usables.add_module mod
|
50
50
|
target.send options[:method], mod
|
51
51
|
end
|
52
52
|
|
data/lib/usable/version.rb
CHANGED
data/lib/usable.rb
CHANGED
@@ -5,10 +5,35 @@ require 'usable/mod_extender'
|
|
5
5
|
require 'usable/config'
|
6
6
|
|
7
7
|
module Usable
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
# @description Define an instance level version of +usables+
|
10
|
+
def self.extended(base)
|
11
|
+
base.class_eval do
|
12
|
+
def usables
|
13
|
+
self.class.usables
|
14
|
+
end
|
15
|
+
|
16
|
+
def usable_method(method_name)
|
17
|
+
self.class.usable_method(self, method_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
unless base.is_a? Class
|
21
|
+
base.instance_eval do
|
22
|
+
def config(&block)
|
23
|
+
usables(&block)
|
24
|
+
end unless defined? config
|
25
|
+
end
|
26
|
+
end
|
10
27
|
end
|
11
|
-
|
28
|
+
|
29
|
+
# @description Read and write configuration options
|
30
|
+
def usables
|
31
|
+
@usables ||= Config.new
|
32
|
+
return @usables unless block_given?
|
33
|
+
@usables.instance_eval &Proc.new
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_writer :usables
|
12
37
|
|
13
38
|
# @description Configures the +available_methods+ of a module using the given options or block and then includes it on
|
14
39
|
# the target class. Checks if there is a module named UsableSpec within the given mods namespace and uses the instance
|
@@ -18,8 +43,8 @@ module Usable
|
|
18
43
|
#
|
19
44
|
# class Example
|
20
45
|
# extend Usable
|
21
|
-
# usable Mixin, only: [:foo, :bar] do
|
22
|
-
#
|
46
|
+
# usable Mixin, only: [:foo, :bar] do
|
47
|
+
# baz "Available as `Example.usables.baz` or `Example.usables.mixin.baz`"
|
23
48
|
# end
|
24
49
|
# end
|
25
50
|
#
|
@@ -32,13 +57,22 @@ module Usable
|
|
32
57
|
# @option [Array,Symbol] :only Limit which methods are copied from the module
|
33
58
|
# @option [String,Symbol] :method (:include) The method to use for including the module
|
34
59
|
# @return [ModExtender] containing the original and modified module
|
35
|
-
def usable(mod, options = {})
|
60
|
+
def usable(mod, options = {}, &block)
|
36
61
|
usable_options = { only: options.delete(:only), method: options.delete(:method) }
|
37
|
-
|
38
|
-
|
62
|
+
# Define settings on @usables and on the scoped @usables
|
63
|
+
scope = Config.new
|
64
|
+
if mod.name
|
65
|
+
scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase
|
66
|
+
usables[scope_name] = scope
|
67
|
+
end
|
68
|
+
if mod.respond_to? :usables
|
69
|
+
mod.usables.each do |k, v|
|
70
|
+
[scope, usables].each { |x| x.spec k, v }
|
71
|
+
end
|
39
72
|
end
|
40
|
-
options.each { |k, v|
|
41
|
-
|
73
|
+
[scope, usables].each { |x| options.each { |k, v| x[k] = v } }
|
74
|
+
[scope, usables].each { |x| x.instance_eval &block } if block_given?
|
75
|
+
# Include module
|
42
76
|
mod_ext = ModExtender.new mod, usable_options
|
43
77
|
mod_ext.use! self
|
44
78
|
mod_ext.use_original! self
|
@@ -48,6 +82,6 @@ module Usable
|
|
48
82
|
|
49
83
|
# @return [Method] bound to the given -context-
|
50
84
|
def usable_method(context, method_name)
|
51
|
-
|
85
|
+
usables.available_methods[method_name].bind(context)
|
52
86
|
end
|
53
87
|
end
|
data/usable.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["arebuckley@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{Mounts and configures modules}
|
13
|
-
spec.description = %q{
|
13
|
+
spec.description = %q{Usable provides an elegant way to mount and configure your modules}
|
14
14
|
spec.homepage = "https://github.com/ridiculous/usable"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
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:
|
4
|
+
version: 2.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-04-
|
11
|
+
date: 2016-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,8 +58,7 @@ dependencies:
|
|
58
58
|
- - "<"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '4'
|
61
|
-
description:
|
62
|
-
control over which methods are included.
|
61
|
+
description: Usable provides an elegant way to mount and configure your modules
|
63
62
|
email:
|
64
63
|
- arebuckley@gmail.com
|
65
64
|
executables: []
|