callable 0.0.1 → 0.0.2
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/README.md +81 -44
- data/callable.gemspec +2 -1
- data/lib/callable.rb +19 -1
- data/lib/callable/version.rb +1 -1
- data/spec/callable_spec.rb +78 -0
- data/spec/spec_helper.rb +5 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e85b170016fdbc135bebf0884c38e5637907d77a
|
4
|
+
data.tar.gz: 040b7e0d547142f84b52b547594171f3fcaa29f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ff80b6c79dd75efe33e43c156ef738354470e1a2ad61c67b05cef612e9abeb339900dce8c2f193bf69ed772d28bdb7902150f6fc9c1a77ee1f4a7e3867b24ab
|
7
|
+
data.tar.gz: 72ecb0cf755932c829ceeefc659b5960770836ed2fcdb377910c0283abf555cd0ca776d96de7aaba410e5a533a7357733ad58bc6464d99d13d6216563dbb88ce
|
data/README.md
CHANGED
@@ -26,71 +26,108 @@ in one of two ways (don't forget to install the gem first).
|
|
26
26
|
The first way is by invoking the callable method:
|
27
27
|
|
28
28
|
```ruby
|
29
|
-
c = Callable( :ret_val )
|
30
|
-
c.call
|
31
|
-
=> ret_val
|
29
|
+
c = Callable( :ret_val )
|
30
|
+
c.call
|
31
|
+
=> ret_val
|
32
32
|
```
|
33
33
|
|
34
34
|
Take into account that if you pass a callable object (such as a
|
35
35
|
lambda), you'll get it back as the return value:
|
36
36
|
|
37
37
|
```ruby
|
38
|
-
c = Callable( ->{ :ret_val } )
|
39
|
-
c.call
|
40
|
-
=> ret_val
|
38
|
+
c = Callable( ->{ :ret_val } )
|
39
|
+
c.call
|
40
|
+
=> ret_val
|
41
41
|
```
|
42
42
|
|
43
|
-
The
|
44
|
-
|
43
|
+
The gem also ships with a #callable? method thar returns true if the
|
44
|
+
object is callable and false if it's not.
|
45
45
|
|
46
46
|
```ruby
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
:not_callable.callable?
|
48
|
+
=> false
|
49
|
+
|
50
|
+
->{ :not_callable }.callable?
|
51
|
+
=> true
|
50
52
|
```
|
51
53
|
|
52
|
-
|
54
|
+
This is the same as saying
|
53
55
|
|
54
56
|
```ruby
|
55
|
-
|
56
|
-
c.call
|
57
|
-
=> ret_val
|
57
|
+
xxx.respond_to? :call
|
58
58
|
```
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
But I felt it would be more illustrative of it's purpose.
|
61
|
+
|
62
|
+
## Where to use it?
|
63
|
+
|
64
|
+
I think the main use for this library is handling actions as options.
|
65
|
+
|
66
|
+
For example, imagine we have a very reduced authorization library that provides a method called `do_if`.
|
67
|
+
This method receives:
|
68
|
+
- a symbol representing a permission name
|
69
|
+
- a Hash that represents the available authorization policies
|
70
|
+
- a block with the actions to perform
|
71
|
+
|
72
|
+
The premise is that the method will execute the block if the selected policy returns true when we send the `call` message.
|
73
|
+
|
74
|
+
Our first approach is:
|
62
75
|
|
63
76
|
```ruby
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
=> true
|
77
|
+
def do_if(permission, policies=POLICIES)
|
78
|
+
yield if policies[permission].call
|
79
|
+
end
|
68
80
|
```
|
69
81
|
|
70
|
-
|
82
|
+
So, if our POLICIES hash is:
|
71
83
|
|
72
84
|
```ruby
|
73
|
-
|
85
|
+
POLICIES = {
|
86
|
+
development: -> { true }
|
87
|
+
}
|
88
|
+
|
89
|
+
do_if(:development) do
|
90
|
+
puts "Debugging"
|
91
|
+
end
|
92
|
+
|
93
|
+
# >> Debugging
|
74
94
|
```
|
75
95
|
|
76
|
-
|
96
|
+
And if we switch the policy value:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
POLICIES = {
|
100
|
+
development: -> { false }
|
101
|
+
}
|
102
|
+
|
103
|
+
do_if(:development) do
|
104
|
+
puts "Debugging"
|
105
|
+
end
|
106
|
+
|
107
|
+
# >>
|
108
|
+
```
|
109
|
+
|
110
|
+
This allows us to have a lot of flexibility. But we could provide the user a way to say the same with less code:
|
111
|
+
|
112
|
+
|
113
|
+
|
77
114
|
|
78
|
-
## Where to use it?
|
79
115
|
|
80
|
-
|
81
|
-
|
116
|
+
*******************************
|
117
|
+
Let me say where to use this gem with a very
|
118
|
+
trivial example.
|
82
119
|
|
83
120
|
Imagine we have some class that admits an informer object that
|
84
121
|
responds to the get_info method and returns a some information on a
|
85
122
|
String.
|
86
123
|
|
87
124
|
```ruby
|
88
|
-
class SomeClass
|
89
|
-
|
90
|
-
|
91
|
-
|
125
|
+
class SomeClass
|
126
|
+
attr_writer :informer
|
127
|
+
def info
|
128
|
+
@informer.get_info
|
129
|
+
end
|
92
130
|
end
|
93
|
-
end
|
94
131
|
```
|
95
132
|
|
96
133
|
If we want to use this "informer" object, we must define a new class
|
@@ -101,25 +138,25 @@ method "call", instead of "get_info", because we now can toss a simple
|
|
101
138
|
lambda to substitute it. We can rewrite the code above like this:
|
102
139
|
|
103
140
|
```ruby
|
104
|
-
class SomeClass
|
105
|
-
|
106
|
-
|
107
|
-
|
141
|
+
class SomeClass
|
142
|
+
attr_writer :informer
|
143
|
+
def info
|
144
|
+
@informer.call
|
145
|
+
end
|
108
146
|
end
|
109
|
-
end
|
110
147
|
```
|
111
148
|
|
112
149
|
And now we can define a class or module that responds to the call
|
113
150
|
method. In that call method, we can get as fancy as we want:
|
114
151
|
|
115
152
|
```ruby
|
116
|
-
module Informer
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
153
|
+
module Informer
|
154
|
+
def call
|
155
|
+
# retrieve the information we need from wherever we want
|
156
|
+
# maybe a web service
|
157
|
+
# maybe a local file
|
158
|
+
end
|
121
159
|
end
|
122
|
-
end
|
123
160
|
```
|
124
161
|
|
125
162
|
So, when we do:
|
@@ -149,7 +186,7 @@ thing like this:
|
|
149
186
|
|
150
187
|
```ruby
|
151
188
|
something = SomeClass.new
|
152
|
-
something.informer = Callable
|
189
|
+
something.informer = Callable("No info available" )
|
153
190
|
something.info
|
154
191
|
```
|
155
192
|
|
data/callable.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'callable/version'
|
@@ -22,3 +21,5 @@ Gem::Specification.new do |spec|
|
|
22
21
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
22
|
spec.add_development_dependency "matest", "~> 1.5"
|
24
23
|
end
|
24
|
+
|
25
|
+
|
data/lib/callable.rb
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
require "callable/version"
|
2
2
|
|
3
3
|
module Callable
|
4
|
-
|
4
|
+
def Callable( callable_or_not )
|
5
|
+
if callable_or_not.respond_to?(:call)
|
6
|
+
callable_or_not
|
7
|
+
else
|
8
|
+
proc { |*args| callable_or_not }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def callable
|
13
|
+
Callable(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def callable?
|
17
|
+
self.respond_to?(:call)
|
18
|
+
end
|
5
19
|
end
|
20
|
+
|
21
|
+
::Object.include(Callable)
|
22
|
+
|
23
|
+
puts "X" * 100
|
data/lib/callable/version.rb
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
scope Callable do
|
4
|
+
spec "creates a callable object" do
|
5
|
+
@obj = :not_callable
|
6
|
+
@c = Callable(@obj)
|
7
|
+
|
8
|
+
@c.call == @obj
|
9
|
+
end
|
10
|
+
|
11
|
+
spec "leaves a callable object intact" do
|
12
|
+
@obj = -> { :callable }
|
13
|
+
@c = Callable(@obj)
|
14
|
+
|
15
|
+
@c == @obj
|
16
|
+
end
|
17
|
+
|
18
|
+
scope "#callable" do
|
19
|
+
spec "creates a callable object" do
|
20
|
+
@obj = :not_callable
|
21
|
+
@c = @obj.callable
|
22
|
+
|
23
|
+
@c.call == @obj
|
24
|
+
end
|
25
|
+
|
26
|
+
spec "leaves a callable object intact" do
|
27
|
+
@obj = -> { :callable }
|
28
|
+
@c = @obj.callable
|
29
|
+
|
30
|
+
@c == @obj
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
scope "#callable?" do
|
36
|
+
spec "returns true if the object responds to #call" do
|
37
|
+
@obj = -> { :callable }
|
38
|
+
|
39
|
+
@obj.callable?
|
40
|
+
end
|
41
|
+
|
42
|
+
spec "returns false if the object doesn't respond to #call" do
|
43
|
+
@obj = :not_callable
|
44
|
+
|
45
|
+
! @obj.callable?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
scope "arguments" do
|
50
|
+
spec "accepts arguments arguments" do
|
51
|
+
@obj = :not_callable
|
52
|
+
@c = Callable(@obj)
|
53
|
+
|
54
|
+
@c.call(1, 2, 3) == @obj
|
55
|
+
end
|
56
|
+
|
57
|
+
spec "passes the arguments on" do
|
58
|
+
@obj = -> (a, b) { a + " " + b }
|
59
|
+
@c = Callable(@obj)
|
60
|
+
|
61
|
+
@c.call("Call", "me") == "Call me"
|
62
|
+
end
|
63
|
+
|
64
|
+
spec "can pass any number of arguments to a proc" do
|
65
|
+
@obj = proc { |a, b| a + " " + b }
|
66
|
+
@c = Callable(@obj)
|
67
|
+
|
68
|
+
@c.call("Call", "me", "now") == "Call me"
|
69
|
+
end
|
70
|
+
|
71
|
+
spec "passes the arguments on" do
|
72
|
+
@obj = -> (*args) { args.join(" ") }
|
73
|
+
@c = Callable(@obj)
|
74
|
+
|
75
|
+
@c.call("Call", "me", "now") == "Call me now"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: callable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Federico Iachetti
|
@@ -68,6 +68,8 @@ files:
|
|
68
68
|
- callable.gemspec
|
69
69
|
- lib/callable.rb
|
70
70
|
- lib/callable/version.rb
|
71
|
+
- spec/callable_spec.rb
|
72
|
+
- spec/spec_helper.rb
|
71
73
|
homepage: ''
|
72
74
|
licenses:
|
73
75
|
- MIT
|
@@ -92,4 +94,6 @@ rubygems_version: 2.4.5
|
|
92
94
|
signing_key:
|
93
95
|
specification_version: 4
|
94
96
|
summary: It allows you to define callable objects.
|
95
|
-
test_files:
|
97
|
+
test_files:
|
98
|
+
- spec/callable_spec.rb
|
99
|
+
- spec/spec_helper.rb
|