invokable 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8be1208734fdbbf1e11e1974834bfb6a65e294c7814a7df1f65775b4a898ae9
4
- data.tar.gz: 2693e344b7eb7c1e9e12615c1c6831b6c842219adf39e70aa924bbd65c7edaee
3
+ metadata.gz: b107ca53f8d89104fa38152d27141d24ae62dbec10e8e313b1428b5e711f61e9
4
+ data.tar.gz: b17e3b4207c4262637a08975772063f8d99583c6ef472220e18598885c272860
5
5
  SHA512:
6
- metadata.gz: 2bc791de5268235f8f7f2715e14f7d14bd6d6155f38aafa85f5a976e037a81b0df57e03def253fb9d55d3881e9845db243a6fffc723cc306d2536b0daa15c931
7
- data.tar.gz: e36ab920d191d24022954f4cd4d055db571390a7e7e0252a8ad38b456283b344678d534bebf58cbe96b0653af2c10e745ca96de0969a10d8371da4b54c361d48
6
+ metadata.gz: c036b555078552a8902b83ccb7800ce878c23844a3ac6c7586d510622a56ba9ef0e4da985773662d5a605566308bb1c835b28eb988b417cc5a42a1c92aa95464
7
+ data.tar.gz: 900fab835907e7a8af2f8284629361ed0fbe1db81e6d05d8a2a98152fc223e4a44de352eb1eba538a9e53d406e95d97bcf4ad82f133a96e91c282626999175a7
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ ## 0.4.2
4
+
5
+ - `invokable/array` is no longer loaded with `invokable/data`.
6
+ This created a bit of havok in a few places. Including breaking
7
+ puma bootup in Rails 5.2.4.1.
8
+
9
+ ## 0.5.0
10
+
11
+ - Added `Invokable::Command` and `Invokable::Core#arity`
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- invokable (0.4.0)
4
+ invokable (0.5.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -20,7 +20,7 @@ GEM
20
20
  pry (0.12.2)
21
21
  coderay (~> 1.1.0)
22
22
  method_source (~> 0.9.0)
23
- rake (10.5.0)
23
+ rake (13.0.1)
24
24
  regexp-examples (1.5.1)
25
25
  rspec (3.9.0)
26
26
  rspec-core (~> 3.9.0)
@@ -45,7 +45,7 @@ DEPENDENCIES
45
45
  gen-test
46
46
  invokable!
47
47
  pry
48
- rake (~> 10.0)
48
+ rake (~> 13.0)
49
49
  rspec (~> 3.0)
50
50
  yard
51
51
 
data/README.md CHANGED
@@ -8,50 +8,78 @@ 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/closure'
53
+
54
+ class TwitterPoster
55
+ include Invokable::Closure
56
+
57
+ enclose :model
58
+
59
+ def call(user)
60
+ # do the dirt
61
+ ...
62
+ TwitterStatus.new(user, data)
63
+ end
64
+ end
65
+
66
+ TwitterPoster.call(Model.find(1)) # => #<TwitterPoster ...>
67
+ TwitterPoster.call(Model.find(1), current_user) # => #<TwitterStatus ...>
68
+
69
+ # both the class and it's instances can be used any where Procs are.
70
+
71
+ Model.where(created_at: Date.today).map(&:TwitterPoster) # => [#<TwitterPoster ...>, ...]
45
72
  ```
46
73
 
47
74
  Use as much or a little as you need:
48
75
 
49
76
  ```ruby
50
77
  require 'invokable' # loads Invokable module
78
+ require 'invokable/closure' # loads Invokable::Closure module
51
79
  require 'invokable/hash' # loads hash patch
52
80
  require 'invokable/array' # loads array patch
53
81
  require 'invokable/set' # loads set patch
54
- require 'invokable/data' # loads hash, array, and set patches
82
+ require 'invokable/data' # loads hash and set patches
55
83
  ```
56
84
 
57
85
  ## Why?
@@ -99,7 +127,7 @@ Returns a curried proc. If the `arity` is given, it determines the number of arg
99
127
 
100
128
  ### `memoize => Proc`
101
129
 
102
- Returns a memoized proc, that is, a proc that caches it return values by it's arguments.
130
+ Returns a memoized proc, that is, a proc that caches it's return values by it's arguments.
103
131
 
104
132
  ### `<<(invokable) => Proc`
105
133
 
@@ -111,6 +139,7 @@ Returns a proc that is a composition of this invokable and the given invokable.
111
139
 
112
140
  ## See Also
113
141
 
142
+ - [Closures and Objects are Equivalent](http://wiki.c2.com/?ClosuresAndObjectsAreEquivalent)
114
143
  - [Clojure](https://clojure.org)
115
144
  - [Arc](http://www.arclanguage.org)
116
145
 
@@ -37,6 +37,6 @@ Gem::Specification.new do |spec|
37
37
  spec.require_paths = ["lib"]
38
38
 
39
39
  spec.add_development_dependency "bundler", "~> 1.17"
40
- spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "rake", "~> 13.0"
41
41
  spec.add_development_dependency "rspec", "~> 3.0"
42
42
  end
@@ -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,116 @@
1
+ module Invokable
2
+ # Treat classes 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.2
7
+ module Closure
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
+ return @initializer_arity if @initializer_arity
35
+
36
+ @initializer ? @initializer.arity : 0
37
+ end
38
+
39
+ # Handle automatic currying--will accept either the initializer arity or the total arity of the class. If
40
+ # the initializer arity is used return a class instance. If the total arity is used instantiate the class
41
+ # and return the results of the `call` method.
42
+ #
43
+ # @version 0.5.0
44
+ # @see arity
45
+ # @see initializer_arity
46
+ def call(*args)
47
+ if args.length == initializer_arity
48
+ new(*args)
49
+ elsif args.length == arity
50
+ init_args = args.slice(0, initializer_arity)
51
+ call_args = args.slice(initializer_arity, args.length)
52
+ new(*init_args).call(*call_args)
53
+ else
54
+ raise ArgumentError, "wrong number of arguments (given #{args.length}, expected #{initializer_arity} or #{arity})"
55
+ end
56
+ end
57
+
58
+ # Specify any enclosed state with a block or named attributes
59
+ #
60
+ # @example
61
+ # class TwitterPater
62
+ # include Invokable::Command
63
+ #
64
+ # enclose :api_key
65
+ #
66
+ # def call(user)
67
+ # # interact with twitter, return results
68
+ # end
69
+ # end
70
+ #
71
+ # TwitterPater.new(API_KEY).call(User.find(1))
72
+ # TwitterPater.new(API_KEY).api_key == API_KEY # => true
73
+ #
74
+ # class TwitterPater
75
+ # include Invokable::Command
76
+ #
77
+ # enclose do |api_key|
78
+ # @api_key = api_key
79
+ # end
80
+ #
81
+ # def call(user)
82
+ # # interact with twitter, return results
83
+ # end
84
+ # end
85
+ #
86
+ # TwitterPater.new(API_KEY).call(User.find(1))
87
+ # TwitterPater.new(API_KEY).api_key # error 'method' missing
88
+ def enclose(*names, &block)
89
+ return define_initializer_with_block(block) unless block.nil?
90
+
91
+ define_initializer_with_names(names)
92
+ end
93
+
94
+ private
95
+
96
+ def define_initializer_with_block(block)
97
+ @initializer = block
98
+ define_method :initialize, &block
99
+ end
100
+
101
+ def define_initializer_with_names(names)
102
+ @initializer_arity = names.length
103
+
104
+ names.each do |name|
105
+ attr_reader name
106
+ end
107
+
108
+ define_method :initialize do |*args|
109
+ names.each_with_index do |name, i|
110
+ instance_variable_set(:"@#{name}", args[i])
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'closure'
2
+
3
+ module Invokable
4
+ # Treat "Command Objects" as curried functions
5
+ #
6
+ # @see https://ruby-doc.org/core-2.7.0/Proc.html#method-i-curry Proc#curry
7
+ #
8
+ # @version 0.5.0
9
+ module Command
10
+ def self.included(klass)
11
+ klass.include(Invokable)
12
+ klass.extend(Invokable::Core)
13
+ klass.extend(Invokable::Compose)
14
+ klass.extend(Invokable::Closure::ClassMethods)
15
+ end
16
+ end
17
+ 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,4 +1,2 @@
1
- require_relative 'core'
2
1
  require_relative 'hash'
3
2
  require_relative 'set'
4
- require_relative 'array'
@@ -1,3 +1,3 @@
1
1
  module Invokable
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.2"
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.0
4
+ version: 0.5.2
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-02-11 00:00:00.000000000 Z
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,6 +63,7 @@ files:
63
63
  - ".github/workflows/ruby.yml"
64
64
  - ".gitignore"
65
65
  - ".rspec"
66
+ - CHANGELOG.md
66
67
  - Gemfile
67
68
  - Gemfile.lock
68
69
  - LICENSE.txt
@@ -71,6 +72,8 @@ files:
71
72
  - invokable.gemspec
72
73
  - lib/invokable.rb
73
74
  - lib/invokable/array.rb
75
+ - lib/invokable/closure.rb
76
+ - lib/invokable/command.rb
74
77
  - lib/invokable/compose.rb
75
78
  - lib/invokable/core.rb
76
79
  - lib/invokable/data.rb
@@ -88,7 +91,7 @@ metadata:
88
91
  source_code_uri: https://github.com/delonnewman/invokable
89
92
  changelog_uri: https://github.com/delonnewman/invokable#changelog
90
93
  documentation_uri: https://www.rubydoc.info/gems/invokable
91
- post_install_message:
94
+ post_install_message:
92
95
  rdoc_options: []
93
96
  require_paths:
94
97
  - lib
@@ -104,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
107
  version: '0'
105
108
  requirements: []
106
109
  rubygems_version: 3.0.6
107
- signing_key:
110
+ signing_key:
108
111
  specification_version: 4
109
112
  summary: Objects are functions! Treat any Object, Hashes, Arrays and Sets as Procs
110
113
  (like Enumerable but for Proc-like objects)