invokable 0.4.2 → 0.5.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 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)