invokable 0.4.2 → 0.5.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
  SHA256:
3
- metadata.gz: 0f703edf97638d502bd35c3717fb629355e17f7f1d2468376698baec50c8b495
4
- data.tar.gz: a04e0e82205103781a0fff545a3a8dceb37a9eebf0103c01996331b4a060d877
3
+ metadata.gz: 6dcc085ff857ef0a95578db5f816338c0ade3da6ef4ecb263f86924e4b4e2cfb
4
+ data.tar.gz: 235f058b7b39b8ff91b8d2580281fad56a388fcea46d19ae3a4bc3657c913d1c
5
5
  SHA512:
6
- metadata.gz: e79339f1c7b207ac86f2c083009e6a51972099e57fa03e3c45f45bb1b0dddf2f9c1f3fd33adab6230dac951466f3fba9b9671130c40af283ff9d2439f98fe919
7
- data.tar.gz: 87263922f9790fc9dda1acc43df77cd0c3077f57998d2364ad91bdd27b2d0495455369a3a18c8026eac2623d4d2f32e1e05b61a89f9e2d55e15197329848a7cd
6
+ metadata.gz: bc8294c008fedd2a69337d886515b8fb9c3a2dd6fea8330b15371ffa9b44db0a5ce3c679badede4e2455230db25845ac723b11aa6736f9b62d690b462f7623e9
7
+ data.tar.gz: f6cab459416371d902933ee1ef3fd24f935bcc0ad7b6c9e0a9bd261bf95d8736c763ec416b94b063acf52fbc4a08df04586ac4b6bde8c02aedcb47b8f8074ef9
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- invokable (0.4.2)
4
+ invokable (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -8,46 +8,76 @@ Objects are functions! Treat any Object, Hashes, Arrays, and Sets as Procs (like
8
8
  ## Synopsis
9
9
 
10
10
  ```ruby
11
- require 'invokable/hash'
11
+ require 'invokable'
12
+ require 'invokable/hash'
12
13
 
13
- number_names = { 1 => "One", 2 => "Two", 3 => "Three" }
14
- [1, 2, 3, 4].map(&number_names) # => ["One", "Two", "Three", nil]
14
+ number_names = { 1 => "One", 2 => "Two", 3 => "Three" }
15
+ [1, 2, 3, 4].map(&number_names) # => ["One", "Two", "Three", nil]
15
16
  ```
16
17
 
17
18
  ```ruby
18
- require 'invokable/array'
19
+ require 'invokable'
20
+ require 'invokable/array'
19
21
 
20
- alpha = ('a'..'z').to_a
21
- [1, 2, 3, 4].map(&alpha) # => ["b", "c", "d", "e"]
22
+ alpha = ('a'..'z').to_a
23
+ [1, 2, 3, 4].map(&alpha) # => ["b", "c", "d", "e"]
22
24
  ```
23
25
 
24
26
  ```ruby
25
- require 'invokable/set'
27
+ require 'invokable'
28
+ require 'invokable/set'
26
29
 
27
- favorite_numbers = Set[3, Math::PI]
28
- [1, 2, 3, 4].select(&favorite_numbers) # => [3]
30
+ favorite_numbers = Set[3, Math::PI]
31
+ [1, 2, 3, 4].select(&favorite_numbers) # => [3]
29
32
  ```
30
33
 
31
34
  ```ruby
32
- require 'invokable'
35
+ # service objects
36
+ require 'invokable'
33
37
 
34
- # service objects
35
- class GetDataFromSomeService
36
- include Invokable
38
+ class GetDataFromSomeService
39
+ include Invokable
37
40
 
38
- def call(user)
39
- # do the dirt
40
- end
41
+ def call(user)
42
+ # do the dirt
41
43
  end
44
+ end
42
45
 
43
- data_for_user = GetDataFromSomeService.new.memoize # 'memoize' makes a proc that caches results
44
- User.all.map(&data_for_user)
46
+ data_for_user = GetDataFromSomeService.new.memoize # 'memoize' makes a proc that caches results
47
+ User.all.map(&data_for_user)
48
+ ```
49
+ ```ruby
50
+ # command objects that enclose state, can be treated as automatically curried functions.
51
+ require 'invokable'
52
+ require 'invokable/command'
53
+
54
+ class TwitterPoster
55
+ include Invokable::Command
56
+
57
+ enclose do |model|
58
+ @model = model
59
+ end
60
+
61
+ def call(user)
62
+ # do the dirt
63
+ ...
64
+ TwitterStatus.new(user, data)
65
+ end
66
+ end
67
+
68
+ TwitterPoster.call(Model.find(1)) # => #<TwitterPoster ...>
69
+ TwitterPoster.call(Model.find(1), current_user) # => #<TwitterStatus ...>
70
+
71
+ # both the class and it's instances can be used any where Procs are.
72
+
73
+ Model.where(created_at: Date.today).map(&:TwitterPoster) # => [#<TwitterPoster ...>, ...]
45
74
  ```
46
75
 
47
76
  Use as much or a little as you need:
48
77
 
49
78
  ```ruby
50
79
  require 'invokable' # loads Invokable module
80
+ require 'invokable/command' # loads Invokable::Command module
51
81
  require 'invokable/hash' # loads hash patch
52
82
  require 'invokable/array' # loads array patch
53
83
  require 'invokable/set' # loads set patch
@@ -111,6 +141,7 @@ Returns a proc that is a composition of this invokable and the given invokable.
111
141
 
112
142
  ## See Also
113
143
 
144
+ - [Closures and Objects are Equivalent](http://wiki.c2.com/?ClosuresAndObjectsAreEquivalent)
114
145
  - [Clojure](https://clojure.org)
115
146
  - [Arc](http://www.arclanguage.org)
116
147
 
@@ -2,6 +2,7 @@ require 'invokable/version'
2
2
  require 'invokable/core'
3
3
  require 'invokable/compose'
4
4
 
5
+ # TODO: make use of Gem::Version
5
6
  if RUBY_VERSION.split('.').take(2).join('.').to_f < 2.6
6
7
  require 'invokable/proc'
7
8
  require 'invokable/method'
@@ -0,0 +1,65 @@
1
+ module Invokable
2
+ # Treat "Command Objects" as curried functions
3
+ #
4
+ # @see https://ruby-doc.org/core-2.7.0/Proc.html#method-i-curry Proc#curry
5
+ #
6
+ # @version 0.5.0
7
+ module Command
8
+ def self.included(klass)
9
+ klass.include(Invokable)
10
+ klass.extend(Invokable::Core)
11
+ klass.extend(Invokable::Compose)
12
+ klass.extend(ClassMethods)
13
+ end
14
+
15
+ module ClassMethods
16
+ # Return the "total" arity of the class (i.e. the arity of the initializer and the arity of the call method)
17
+ #
18
+ # @version 0.5.0
19
+ # @see https://ruby-doc.org/core-2.7.1/Proc.html#method-i-arity Proc#arity
20
+ # @see initializer_arity
21
+ #
22
+ # @return [Integer]
23
+ def arity
24
+ initializer_arity + instance_method(:call).arity
25
+ end
26
+
27
+ # Return the arity of the initializer
28
+ #
29
+ # @version 0.5.0
30
+ # @see arity
31
+ #
32
+ # @return [Integer]
33
+ def initializer_arity
34
+ @initializer ? @initializer.arity : 0
35
+ end
36
+
37
+ # To specify any enclosed state
38
+ def enclose(&block)
39
+ raise 'A block is required' if block.nil?
40
+
41
+ @initializer = block
42
+ define_method :initialize, &block
43
+ end
44
+
45
+ # Handle automatic currying--will accept either the initializer arity or the total arity of the class. If
46
+ # the initializer arity is used return a class instance. If the total arity is used instantiate the class
47
+ # and return the results of the `call` method.
48
+ #
49
+ # @version 0.5.0
50
+ # @see arity
51
+ # @see initializer_arity
52
+ def call(*args)
53
+ if args.length == initializer_arity
54
+ new(*args)
55
+ elsif args.length == arity
56
+ init_args = args.slice(0, initializer_arity)
57
+ call_args = args.slice(initializer_arity, args.length)
58
+ new(*init_args).call(*call_args)
59
+ else
60
+ raise "Wrong number of arguments expected #{initializer_arity} or #{arity}, got: #{args.length}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -36,5 +36,14 @@ module Invokable
36
36
  @memo[args.hash] ||= call(*args)
37
37
  end
38
38
  end
39
+
40
+ # Return the arity (i.e. the number of arguments) of the `call` method.
41
+ #
42
+ # @version 0.5.0
43
+ # @see https://ruby-doc.org/core-2.7.1/Proc.html#method-i-arity Proc#arity
44
+ # @return [Integer]
45
+ def arity
46
+ method(:call).arity
47
+ end
39
48
  end
40
49
  end
@@ -1,3 +1,2 @@
1
- require_relative 'core'
2
1
  require_relative 'hash'
3
2
  require_relative 'set'
@@ -1,3 +1,3 @@
1
1
  module Invokable
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: invokable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delon Newman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-19 00:00:00.000000000 Z
11
+ date: 2020-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -72,6 +72,7 @@ files:
72
72
  - invokable.gemspec
73
73
  - lib/invokable.rb
74
74
  - lib/invokable/array.rb
75
+ - lib/invokable/command.rb
75
76
  - lib/invokable/compose.rb
76
77
  - lib/invokable/core.rb
77
78
  - lib/invokable/data.rb
@@ -89,7 +90,7 @@ metadata:
89
90
  source_code_uri: https://github.com/delonnewman/invokable
90
91
  changelog_uri: https://github.com/delonnewman/invokable#changelog
91
92
  documentation_uri: https://www.rubydoc.info/gems/invokable
92
- post_install_message:
93
+ post_install_message:
93
94
  rdoc_options: []
94
95
  require_paths:
95
96
  - lib
@@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  version: '0'
106
107
  requirements: []
107
108
  rubygems_version: 3.0.6
108
- signing_key:
109
+ signing_key:
109
110
  specification_version: 4
110
111
  summary: Objects are functions! Treat any Object, Hashes, Arrays and Sets as Procs
111
112
  (like Enumerable but for Proc-like objects)