proc 0.0.4 → 0.1.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: a33f3939a8156059653e7edde57a9ac0b0ee46ab04bcb1f08ce098073e884358
4
- data.tar.gz: df8c021333f0f03b6acdaa195b2c39035a4054b026fd1f6c09d08df674aef7f9
3
+ metadata.gz: 0f07ae5d056122c93826012896beb760372534d7c2c83193674580517ff31f86
4
+ data.tar.gz: 5cd335938ec4121d5170c27518678d81c27dd3b65ff6b0235be72213e05613e2
5
5
  SHA512:
6
- metadata.gz: 52107c5f8c68d623aead4dab7131fe7ea42c5abc29bf748cb81f2aea80bc0ae2b68447764c02a1d40aca4a21e24521f2bc291e9ae7794bd69d98cb867c7f0959
7
- data.tar.gz: 8bcab50d65564adb5ce355b75dd407f82ccf93dee798c1219def178293978251b6bfff6c588a823eecd52732a6784a971226026f796601941f1866d3d0c00035
6
+ metadata.gz: '08b92c4b033fe05dea3a0db6321c5cea4ce5f8ce3587e3f1b7902b295e7778f95a433e84652f12d71f3eff0e60d2bc53d584cce308bd307e32b54f76ed3213e3'
7
+ data.tar.gz: ef90d03381df7f8f016460cc83f15c14b3b1f9768dd5078588e85591e61d46df628fd63fd7e804d6d7e1975c7dd9749642f4b51ecaa5bf1e7c19896f64155d72
data/README.md CHANGED
@@ -0,0 +1,80 @@
1
+ The `proc` gem lets you call codeless web functions through the proc.dev service.
2
+
3
+ ## Getting Started
4
+
5
+ Install `proc` using the `gem` command from the command line:
6
+
7
+ ```
8
+ gem install proc
9
+ ```
10
+
11
+ You will also need a proc.dev account. Create a free account in seconds at [proc.dev](https://proc.dev/).
12
+
13
+ ## Connecting
14
+
15
+ Sign in to your proc.dev account and locate your secret key. Use the secret to create a client connection:
16
+
17
+ ```ruby
18
+ client = Proc.connect("secret-key")
19
+ ```
20
+
21
+ ## Calling Procs
22
+
23
+ You can call available procs through a connected client:
24
+
25
+ ```ruby
26
+ client.core.string.reverse.call("hello")
27
+ => "olleh"
28
+ ```
29
+
30
+ Requests are sent to proc.dev anytime the `call` method is invoked.
31
+
32
+ ## Callable Contexts
33
+
34
+ Proc lookups create contexts that can be called later:
35
+
36
+ ```ruby
37
+ string = client.core.string
38
+
39
+ string.reverse.call("hello")
40
+ => "olleh"
41
+
42
+ string.truncate.call("hello", length: 3)
43
+ => "hel"
44
+ ```
45
+
46
+ Contexts can be configured with default input and arguments using the `with` method:
47
+
48
+ ```ruby
49
+ truncate = client.core.string.truncate.with("default", length: 1)
50
+
51
+ truncate.call
52
+ => "d"
53
+ ```
54
+
55
+ Default input and/or arguments can be overidden for a specific call:
56
+
57
+ ```ruby
58
+ truncate.call(length: 3)
59
+ => "def"
60
+ ```
61
+
62
+ Procs can also be looked up using the hash key syntax:
63
+
64
+ ```ruby
65
+ client["core.string.truncate"].call("hello", length: 3)
66
+ => "hel"
67
+ ```
68
+
69
+ ## Compositions
70
+
71
+ Procs can be composed together to build more complex behavior:
72
+
73
+ ```ruby
74
+ composition = client.core.string.reverse >> client.core.string.truncate(length: 3) >> client.core.string.capitalize
75
+
76
+ composition.call("hello")
77
+ => "Oll"
78
+ ```
79
+
80
+ Compositions are sent to proc.dev in a single request.
@@ -2,15 +2,26 @@
2
2
 
3
3
  class Proc
4
4
  class Callable
5
- attr_reader :proc
5
+ attr_reader :proc, :input, :arguments
6
6
 
7
- def initialize(proc, client:)
7
+ def initialize(proc, client:, input: nil, arguments: {})
8
8
  @proc = proc
9
9
  @client = client
10
+ @input = input
11
+ @arguments = arguments
10
12
  end
11
13
 
12
- def call(input = nil, **arguments)
13
- @client.call(@proc, input, **arguments)
14
+ def initialize_copy(_)
15
+ @input = input.dup
16
+ @arguments = arguments.dup
17
+ end
18
+
19
+ def call(input = input_omitted = true, **arguments)
20
+ @client.call(@proc, input_omitted ? @input : input, **@arguments.merge(arguments))
21
+ end
22
+
23
+ def with(input = input_omitted = true, **arguments)
24
+ self.class.new(@proc, client: @client, input: input_omitted ? @input : input, arguments: @arguments.merge(arguments))
14
25
  end
15
26
 
16
27
  def >>(other)
@@ -19,5 +30,51 @@ class Proc
19
30
  composed << other
20
31
  composed
21
32
  end
33
+
34
+ def serialize
35
+ {
36
+ "{}" => {
37
+ "<<" => serialize_value(@input),
38
+ "[]" => [[@proc, serialized_arguments]]
39
+ }
40
+ }
41
+ end
42
+
43
+ def serialized_arguments
44
+ @arguments.each_pair.each_with_object({}) { |(key, value), hash|
45
+ hash[key.to_s] = serialize_value(value)
46
+ }
47
+ end
48
+
49
+ IGNORE_MISSING = %i[to_hash].freeze
50
+
51
+ def method_missing(name, input = input_omitted = true, **arguments)
52
+ if IGNORE_MISSING.include?(name)
53
+ super
54
+ else
55
+ Callable.new(
56
+ [@proc, name].join("."),
57
+ client: @client,
58
+ input: input_omitted ? @input : input,
59
+ arguments: @arguments.merge(arguments)
60
+ )
61
+ end
62
+ end
63
+
64
+ def respond_to_missing?(name, *)
65
+ if IGNORE_MISSING.include?(name)
66
+ super
67
+ else
68
+ true
69
+ end
70
+ end
71
+
72
+ private def serialize_value(value)
73
+ if value.respond_to?(:serialize)
74
+ value.serialize
75
+ else
76
+ value
77
+ end
78
+ end
22
79
  end
23
80
  end
@@ -60,9 +60,6 @@ class Proc
60
60
  @resets_at
61
61
  end
62
62
 
63
- def compose(&block)
64
- Composition.new(client: self, &block)
65
- end
66
63
 
67
64
  DEFAULT_HEADERS = {
68
65
  "accept" => "application/json",
@@ -71,14 +68,10 @@ class Proc
71
68
 
72
69
  def call(proc = nil, input = nil, **arguments)
73
70
  Async(logger: NullLogger) { |task|
74
- body = { "<<" => input }
71
+ body = { "<<" => serialize_value(input) }
75
72
 
76
73
  arguments.each_pair do |key, value|
77
- body[key.to_s] = if value.respond_to?(:serialize)
78
- value.serialize
79
- else
80
- value
81
- end
74
+ body[key.to_s] = serialize_value(value)
82
75
  end
83
76
 
84
77
  headers = {
@@ -119,10 +112,26 @@ class Proc
119
112
  }.wait
120
113
  end
121
114
 
115
+ def method_missing(name, input = nil, **arguments)
116
+ Callable.new(name, client: self, input: input, arguments: arguments)
117
+ end
118
+
119
+ def respond_to_missing?(name, *)
120
+ true
121
+ end
122
+
122
123
  private def build_uri(proc)
123
124
  host_and_path = File.join(@host, proc.to_s.split(".").join("/"))
124
125
 
125
126
  "#{@scheme}://#{host_and_path}"
126
127
  end
128
+
129
+ private def serialize_value(value)
130
+ if value.respond_to?(:serialize)
131
+ value.serialize
132
+ else
133
+ value
134
+ end
135
+ end
127
136
  end
128
137
  end
@@ -2,12 +2,8 @@
2
2
 
3
3
  class Proc
4
4
  class Composition
5
- require_relative "composition/deferable"
6
- require_relative "composition/evaluator"
7
-
8
- def initialize(client:, &block)
5
+ def initialize(client:)
9
6
  @client = client
10
- @block = block
11
7
  @callables = []
12
8
  end
13
9
 
@@ -15,10 +11,8 @@ class Proc
15
11
  @callables = @callables.dup
16
12
  end
17
13
 
18
- def call(input = nil, **arguments)
19
- # TODO: This will probably call `proc.run`.
20
- #
21
- @client.call("compose", input, proc: build_evaluator(**arguments))
14
+ def call(input = input_omitted = true, **arguments)
15
+ @client.call("exec", input_omitted ? @callables.first.input : input, proc: serialize)
22
16
  end
23
17
 
24
18
  def >>(other)
@@ -31,28 +25,10 @@ class Proc
31
25
  @callables << callable
32
26
  end
33
27
 
34
- def with(**arguments)
35
- build_evaluator(**arguments)
36
- end
37
-
38
28
  def serialize
39
- build_evaluator.serialize
40
- rescue ::ArgumentError => error
41
- raise ::ArgumentError, error.message + " (try using `with' to build a composition with arguments)"
42
- end
43
-
44
- private def build_evaluator(**arguments)
45
- evaluator = if @block
46
- @block.call(Evaluator.new, **arguments)
47
- else
48
- Evaluator.new
49
- end
50
-
51
- @callables.each do |callable|
52
- evaluator << Deferable.new(callable.proc)
53
- end
54
-
55
- evaluator
29
+ @callables.map { |callable|
30
+ [callable.proc, callable.serialized_arguments]
31
+ }
56
32
  end
57
33
  end
58
34
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Proc
4
- VERSION = "0.0.4"
4
+ VERSION = "0.1.0"
5
5
 
6
6
  def self.version
7
7
  VERSION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Powell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-24 00:00:00.000000000 Z
11
+ date: 2020-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-http
@@ -50,8 +50,6 @@ files:
50
50
  - lib/proc/callable.rb
51
51
  - lib/proc/client.rb
52
52
  - lib/proc/composition.rb
53
- - lib/proc/composition/deferable.rb
54
- - lib/proc/composition/evaluator.rb
55
53
  - lib/proc/http/client.rb
56
54
  - lib/proc/http/request.rb
57
55
  - lib/proc/http/response.rb
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proc
4
- class Composition
5
- class Deferable
6
- attr_reader :proc
7
- attr_writer :arguments
8
-
9
- def initialize(proc)
10
- @proc = proc
11
- @arguments = {}
12
- end
13
-
14
- def serialize
15
- [@proc, serialized_arguments]
16
- end
17
-
18
- private def serialized_arguments
19
- @arguments.each.each_with_object({}) do |(key, value), hash|
20
- hash[key] = if value.respond_to?(:serialize)
21
- value.serialize
22
- else
23
- value
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proc
4
- class Composition
5
- class Evaluator
6
- attr_reader :callables
7
-
8
- def initialize
9
- @callables = []
10
- end
11
-
12
- def initialize_copy(_)
13
- @callables = @callables.map(&:dup)
14
- end
15
-
16
- def [](proc)
17
- evaluator = dup
18
- evaluator << Deferable.new(proc)
19
- evaluator
20
- end
21
-
22
- def <<(proc)
23
- @callables << proc
24
- end
25
-
26
- def >>(other)
27
- evaluator = dup
28
-
29
- case other
30
- when Evaluator
31
- other.callables.each do |each_callable|
32
- evaluator << each_callable
33
- end
34
- when Callable
35
- evaluator << Deferable.new(other.proc)
36
- end
37
-
38
- evaluator
39
- end
40
-
41
- def call(**arguments)
42
- evaluator = dup
43
- evaluator.callables.last.arguments = arguments
44
- evaluator
45
- end
46
-
47
- def serialize
48
- { "[]" => @callables.map(&:serialize) }
49
- end
50
- end
51
- end
52
- end