lownode 0.5.5 → 0.5.6

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: b68fa8f3dbf9758ac2e891d89ce312a9c4a8f36145896ee74bd2f0560665a8a6
4
- data.tar.gz: 35393a675ce46a9ce662e30b337aa7aba83c695b160b1400526277fc2574d270
3
+ metadata.gz: b69423239598da8c8c0879744b80e05c45b57d5b7f8bc281bbb87dadb5054c92
4
+ data.tar.gz: 303f7cac2392a4f84c286e599ae27c673da899421c60970a75390b5d2b50c884
5
5
  SHA512:
6
- metadata.gz: cab4b4836847914e458719b67c8737026481ba4ddc3978c30142f7df8107396c6e30c4a634e193760c74984e6615140ad39581f863aa15637b790ff0561411b9
7
- data.tar.gz: 0c237cc521823800503aa2fefc220456db795c7d10194da9ab29dce656b3510c48752af9e4c1ada70dc36e9b6b32344ca2e2b3454c9d8febc6fe4da0ff509aba
6
+ metadata.gz: a53a9fb3bb5a2fdc045f21db55c5b7f31ccf08c4e9fd18bf50839ad82ea9320b347ee9bc97b00a0b99887b7c51a359dc187b12d6f184974e005f6fbc50ad6d91
7
+ data.tar.gz: 6f944d99e2de080df6657979ad3fb24c263bc13d51a8a52510bc5e6e3db42f2d420223cd8f66aec5700fa766fa3fb73a40a295284a0f9a45f12f57d694962deb
@@ -6,8 +6,27 @@ require 'protocol/http'
6
6
 
7
7
  module Low
8
8
  module Templates
9
- # Use the Method Factory pattern to ".render -> .new -> #initialize -> #render" a LowNode.
9
+ # Use the Method Factory pattern to ".render -> .new -> #initialize -> #render" a LowNode, and the same for its other actions.
10
10
  module Renderer
11
+ # Observers call actions on the node class, which the Method Factory pattern turns into the node's instance methods:
12
+ # ".receive -> .new -> #initialize -> #receive". Defining them up front avoids a method_missing lookup on every event.
13
+ ACTIONS = %i[render receive side_effect].freeze
14
+
15
+ # The HTTP verb actions, which a node has when it does "include Controller".
16
+ CONTROLLER_ACTIONS = %i[get query post put patch delete].freeze
17
+
18
+ # Accepts all arguments but only sends each method the arguments it takes, like initialize(limit:) and render(event:).
19
+ # Defined with "def" rather than "define_method" because a block with keyword arguments is slower to call.
20
+ def self.define_actions(mod, actions)
21
+ actions.each do |action|
22
+ mod.module_eval <<~RUBY, __FILE__, __LINE__ + 1
23
+ def #{action}(**kwargs)
24
+ response_event(body: action_body(:#{action}, kwargs), event: kwargs[:event])
25
+ end
26
+ RUBY
27
+ end
28
+ end
29
+
11
30
  # Antlers hook.
12
31
  # When render() contains RBX/Antlers then dirload builds a template to render with instead.
13
32
  # When lowevent is required then Antlers will send an event keyword argument as well.
@@ -33,18 +52,19 @@ module Low
33
52
  base.extend(ClassMethods)
34
53
  end
35
54
 
36
- module ClassMethods
37
- # Accepts all arguments but only sends each method the arguments it takes, like initialize(limit:) and render(event:).
38
- def render(**kwargs)
39
- # GOAL: Make return value configurable; ResponseEvent, Response, or body.
40
- body = response_body(**kwargs)
41
-
42
- return if body.nil? || body == ''
55
+ # Adds the HTTP verb actions to a node with "include Controller", so it can respond with "def get" and "def post".
56
+ module Controller
57
+ def self.included(base)
58
+ base.extend(ClassMethods)
59
+ end
43
60
 
44
- headers = Protocol::HTTP::Headers.new([['content-type', 'text/html']])
45
- response = Protocol::HTTP::Response.new('HTTP/1.1', response_status(kwargs[:event]), headers, Protocol::HTTP::Body::Buffered.wrap(body.strip))
46
- Low::Events::ResponseEvent.new(response:).tap(&:branch)
61
+ module ClassMethods
62
+ Renderer.define_actions(self, CONTROLLER_ACTIONS)
47
63
  end
64
+ end
65
+
66
+ module ClassMethods
67
+ Renderer.define_actions(self, ACTIONS)
48
68
 
49
69
  # Dirload hook.
50
70
  def template
@@ -58,16 +78,40 @@ module Low
58
78
 
59
79
  private
60
80
 
61
- # Responses default to 200 but when rendering for a StatusEvent use that event's status code.
62
- def response_status(event)
63
- event.is_a?(Low::Events::StatusEvent) ? event.status.status_code : 200
64
- end
81
+ # Only nodes that implement the action are initialized, so a "render" then "get" event initializes a "get" node once.
82
+ def action_body(action, kwargs)
83
+ template = action == :render && @template
84
+ return unless template || method_defined?(action)
65
85
 
66
- def response_body(**kwargs)
67
86
  node = new(**Antlers::Keywords.accepted(instance_method(:initialize), kwargs))
68
- return node.render_template(**kwargs) if @template
87
+ return node.render_template(**kwargs) if template
88
+
89
+ # The action is public, as method_defined? doesn't include private methods.
90
+ node.__send__(action, **Antlers::Keywords.accepted(node.method(action), kwargs))
91
+ end
92
+
93
+ # GOAL: Make return value configurable; ResponseEvent, Response, or body.
94
+ def response_event(body:, event:)
95
+ unless body.is_a?(String)
96
+ return body if body.is_a?(Low::Events::ResponseEvent)
97
+ return status_response_event(status_code: body.status_code) if body.is_a?(Low::Types::Status::StatusCode)
98
+ end
99
+ return if body.nil? || body == ''
69
100
 
70
- node.render(**Antlers::Keywords.accepted(node.method(:render), kwargs))
101
+ headers = Protocol::HTTP::Headers.new([['content-type', 'text/html']])
102
+ response = Protocol::HTTP::Response.new('HTTP/1.1', response_status(event), headers, Protocol::HTTP::Body::Buffered.wrap(body.strip))
103
+ Low::Events::ResponseEvent.new(response:).tap(&:branch)
104
+ end
105
+
106
+ # Actions like "post" can return "Status[200]" to respond without a body.
107
+ def status_response_event(status_code:)
108
+ response = Protocol::HTTP::Response.new('HTTP/1.1', status_code, Protocol::HTTP::Headers.new, nil)
109
+ Low::Events::ResponseEvent.new(response:).tap(&:branch)
110
+ end
111
+
112
+ # Responses default to 200 but when rendering for a StatusEvent use that event's status code.
113
+ def response_status(event)
114
+ event.is_a?(Low::Events::StatusEvent) ? event.status.status_code : 200
71
115
  end
72
116
  end
73
117
  end
data/lib/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Low
4
4
  module Node
5
- VERSION = '0.5.5'
5
+ VERSION = '0.5.6'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lownode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi