phlex-slotable 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +212 -222
- data/benchmark/main.rb +1 -1
- data/lib/phlex/slotable/version.rb +1 -1
- data/lib/phlex/slotable.rb +14 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47c3384e49460492a4ff914af1ecd7c6a16fa2841f90d49a4b83b84c305cf892
|
4
|
+
data.tar.gz: aed5afef686e5f630b98842de12b18cc9f5634dd9f099b07273a7aa281f2915a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02c8d0105b65526025feea5fe1aadd7851a96e8406ccb574c0b7bb45d732e54dc85c98f6fbb182af5f57ae8f404cbe17a879bafad42ef6ce9ecd0c168c286d75
|
7
|
+
data.tar.gz: 76a8bfd794fd7a7040bf1699db0dd3001f9d7de0cac0f641515494307a3cb370ab173588e2ba3610553c601f907d1da3990d5580702c1308c008e6d2ce11a327
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,21 @@
|
|
6
6
|
|
7
7
|
Phlex::Slotable enables slots feature to [Phlex](https://www.phlex.fun/) views. Inspired by ViewComponent.
|
8
8
|
|
9
|
-
|
9
|
+
- [What is a slot?](#what-is-a-slot)
|
10
|
+
- [Getting started](#getting-started)
|
11
|
+
- [Generic slot](#generic-slot)
|
12
|
+
- [Slot collection](#slot-collection)
|
13
|
+
- [Component slot](#component-slot)
|
14
|
+
- [Lambda slot](#lambda-slot)
|
15
|
+
- [Polymorphic slot](#polymorphic-slot)
|
16
|
+
- [Development](#development)
|
17
|
+
- [Contributing](#contributing)
|
18
|
+
|
19
|
+
## What is a slot?
|
20
|
+
|
21
|
+
In the context of view components, a **slot** serves as a placeholder inside a component that can be filled with custom content. Essentially, slots enable a component to accept external content and autonomously organize it within its structure. This abstraction allows developers to work with components without needing to understand their internals, thereby ensuring visual consistency and improving developer experience.
|
22
|
+
|
23
|
+
## Getting started
|
10
24
|
|
11
25
|
Install the gem and add to the application's Gemfile by executing:
|
12
26
|
|
@@ -16,268 +30,272 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
16
30
|
|
17
31
|
$ gem install phlex-slotable
|
18
32
|
|
19
|
-
|
33
|
+
> [!TIP]
|
34
|
+
> If you prefer not to add another dependency to your project, you can simply copy the [Phlex::Slotable](https://github.com/stephannv/phlex-slotable/blob/main/lib/phlex/slotable.rb) file into your project.
|
35
|
+
|
36
|
+
Afterward, simply include `Phlex::Slotable` into your Phlex component and utilize `slot` macro to define the component's slots. For example:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
class MyComponent < Phlex::HTML
|
40
|
+
include Phlex::Slotable
|
41
|
+
|
42
|
+
slot :my_slot
|
43
|
+
end
|
44
|
+
```
|
20
45
|
|
21
|
-
|
46
|
+
Below, you will find a more detailed explanation of how to use the `slot` API.
|
22
47
|
|
23
|
-
|
48
|
+
## Generic slot
|
24
49
|
|
25
|
-
|
26
|
-
- `slot :slot_name, many: true` denotes a slot capable of being rendered multiple times within a view
|
50
|
+
Any content can be passed to components through generic slots, also known as passthrough slots. To define a generic slot, use `slot :{slot_name}`. For example:
|
27
51
|
|
28
52
|
```ruby
|
29
|
-
class
|
53
|
+
class PageComponent < Phlex::HTML
|
30
54
|
include Phlex::Slotable
|
31
55
|
|
32
|
-
slot :
|
33
|
-
slot :post, many: true
|
34
|
-
|
35
|
-
# ...
|
56
|
+
slot :title
|
36
57
|
end
|
37
58
|
```
|
38
59
|
|
39
|
-
To render a
|
40
|
-
|
41
|
-
For multi-slot rendering, iterate over the `{slot_name}_slots` collection and and render each slot individually, eg. `post_slots.each { |s| render s }`.
|
60
|
+
To render a slot, render the `{slot_name}_slot`:
|
42
61
|
|
43
62
|
```ruby
|
44
|
-
class
|
63
|
+
class PageComponent < Phlex::HTML
|
45
64
|
include Phlex::Slotable
|
46
65
|
|
47
|
-
slot :
|
48
|
-
slot :post, many: true
|
66
|
+
slot :title
|
49
67
|
|
50
68
|
def template
|
51
|
-
|
52
|
-
|
53
|
-
|
69
|
+
header { render title_slot }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
54
73
|
|
55
|
-
|
56
|
-
post_slots.each do |slot|
|
57
|
-
p { render slot }
|
58
|
-
end
|
74
|
+
To pass content to the component's slot, you should use `with_{slot_name}`:
|
59
75
|
|
60
|
-
|
61
|
-
|
76
|
+
```ruby
|
77
|
+
PageComponent.new.call do |page|
|
78
|
+
page.with_title do
|
79
|
+
h1 { "Hello World!" }
|
62
80
|
end
|
63
81
|
end
|
64
82
|
```
|
65
83
|
|
66
|
-
|
84
|
+
Returning:
|
85
|
+
|
86
|
+
```html
|
87
|
+
<header>
|
88
|
+
<h1>Hello World!</h1>
|
89
|
+
</header>
|
90
|
+
```
|
91
|
+
|
92
|
+
You can test if a slot has been passed to the component with `{slot_name}_slot?` method. For example:
|
67
93
|
|
68
94
|
```ruby
|
69
|
-
class
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
h1 { "Hello World!" }
|
74
|
-
end
|
95
|
+
class PageComponent < Phlex::HTML
|
96
|
+
include Phlex::Slotable
|
97
|
+
|
98
|
+
slot :title
|
75
99
|
|
76
|
-
|
77
|
-
|
78
|
-
|
100
|
+
def template
|
101
|
+
if header_slot?
|
102
|
+
header { render title_slot }
|
103
|
+
else
|
104
|
+
plain "No title"
|
79
105
|
end
|
80
106
|
end
|
81
107
|
end
|
82
|
-
|
83
|
-
MyPage.new.call
|
84
108
|
```
|
85
109
|
|
86
|
-
|
110
|
+
## Slot collection
|
87
111
|
|
88
|
-
|
89
|
-
<div id="header">
|
90
|
-
<h1>Hello World</h1>
|
91
|
-
</div>
|
92
|
-
<div id="main">
|
93
|
-
<p>Post A</p>
|
94
|
-
<p>Post B</p>
|
95
|
-
<p>Post C</p>
|
112
|
+
A slot collection denotes a slot capable of being rendered multiple times within a component. It has some minor differences compared to a single slot seen previously. First, you should pass `collection: true` when defining the slot:
|
96
113
|
|
97
|
-
|
98
|
-
|
99
|
-
|
114
|
+
```ruby
|
115
|
+
class ListComponent < Phlex::HTML
|
116
|
+
include Phlex::Slotable
|
100
117
|
|
101
|
-
|
118
|
+
slot :item, collection: true
|
119
|
+
end
|
120
|
+
```
|
102
121
|
|
103
|
-
|
122
|
+
To render a collection of slots, iterate over the `{slot_name}_slots` collection and render each slot individually:
|
104
123
|
|
105
124
|
```ruby
|
106
|
-
class
|
107
|
-
|
125
|
+
class ListComponent < Phlex::HTML
|
126
|
+
include Phlex::Slotable
|
108
127
|
|
109
|
-
slot :
|
110
|
-
slot :post, many: true
|
128
|
+
slot :item, collection: true
|
111
129
|
|
112
130
|
def template
|
113
|
-
if
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
div id: "main" do
|
120
|
-
if post_slots?
|
121
|
-
post_slots.each do |slot|
|
122
|
-
p { render slot }
|
131
|
+
if item_slots?
|
132
|
+
ul do
|
133
|
+
item_slots.each do |item_slot|
|
134
|
+
li { render item_slot }
|
123
135
|
end
|
124
|
-
|
125
|
-
span { "Count: #{post_slots.count}" }
|
126
|
-
else
|
127
|
-
span { "No post yet" }
|
128
136
|
end
|
129
137
|
end
|
138
|
+
|
139
|
+
span { "Total: #{item_slots.size}" }
|
130
140
|
end
|
131
141
|
end
|
132
142
|
```
|
133
143
|
|
134
|
-
|
135
|
-
|
136
|
-
Slots have the capability to render other views, Simply pass the view class name to the `slot` method.
|
144
|
+
To set slot content, use the `with_{slot_name}` method when rendering the component. Unlike the single slot, `with_{slot_name}` can be called multiple times:
|
137
145
|
|
138
146
|
```ruby
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
def template(&content)
|
145
|
-
h1(class: "text-#{@size}", &content)
|
146
|
-
end
|
147
|
+
ListComponent.new.call do |list|
|
148
|
+
list.with_item { "Item A" }
|
149
|
+
list.with_item { "Item B" }
|
150
|
+
list.with_item { "Item C" }
|
147
151
|
end
|
152
|
+
```
|
148
153
|
|
149
|
-
|
150
|
-
def initialize(featured:)
|
151
|
-
@featured = featured
|
152
|
-
end
|
154
|
+
Returning:
|
153
155
|
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
```html
|
157
|
+
<ul>
|
158
|
+
<li>Item A</li>
|
159
|
+
<li>Item B</li>
|
160
|
+
<li>Item C</li>
|
161
|
+
</ul>
|
162
|
+
|
163
|
+
<span>Total: 3</span>
|
164
|
+
```
|
165
|
+
|
166
|
+
## Component slot
|
167
|
+
|
168
|
+
Slots have the capability to render other components. When defining a slot, provide the name of a component class as the second argument to define a component slot
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
class ListHeaderComponent < Phlex::HTML
|
172
|
+
# omitted code
|
157
173
|
end
|
158
174
|
|
159
|
-
class
|
175
|
+
class ListItemComponent < Phlex::HTML
|
176
|
+
# omitted code
|
177
|
+
end
|
178
|
+
|
179
|
+
class ListComponent < Phlex::HTML
|
160
180
|
include Phlex::Slotable
|
161
181
|
|
162
|
-
slot :header,
|
163
|
-
slot :
|
182
|
+
slot :header, ListHeaderComponent
|
183
|
+
slot :item, ListItemComponent, collection: true
|
164
184
|
|
165
185
|
def template
|
166
|
-
|
167
|
-
|
168
|
-
render header_slot
|
169
|
-
end
|
186
|
+
div id: "header" do
|
187
|
+
render header_slot if header_slot?
|
170
188
|
end
|
171
189
|
|
172
|
-
|
173
|
-
|
174
|
-
post_slots.each { render slot }
|
175
|
-
|
176
|
-
span { "Count: #{post_slots.count}" }
|
177
|
-
else
|
178
|
-
span { "No post yet" }
|
179
|
-
end
|
190
|
+
ul do
|
191
|
+
item_slots.each { |slot| render slot }
|
180
192
|
end
|
181
193
|
end
|
182
194
|
end
|
183
195
|
|
184
|
-
|
185
|
-
|
186
|
-
render BlogComponent.new do |blog|
|
187
|
-
blog.with_header(size: :lg) { "Hello World!" }
|
196
|
+
ListComponent.new.call do |list|
|
197
|
+
list.with_header(size: "lg") { "Hello World!" }
|
188
198
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
end
|
199
|
+
list.with_item(active: true) { "Item A" }
|
200
|
+
list.with_item { "Item B" }
|
201
|
+
list.with_item { "Item C" }
|
194
202
|
end
|
195
|
-
|
196
|
-
MyPage.new.call
|
197
203
|
```
|
198
204
|
|
199
|
-
|
205
|
+
Returning:
|
200
206
|
|
201
207
|
```html
|
202
208
|
<div id="header">
|
203
|
-
<h1 class="text-lg">Hello World
|
204
|
-
</div>
|
205
|
-
<div id="main">
|
206
|
-
<p class="featured">Post A</p>
|
207
|
-
<p>Post B</p>
|
208
|
-
<p>Post C</p>
|
209
|
+
<h1 class="text-lg">Hello World!</h1>
|
209
210
|
|
210
|
-
<
|
211
|
+
<ul>
|
212
|
+
<li class="active">Item A</li>
|
213
|
+
<li>Item B</li>
|
214
|
+
<li>Item C</li>
|
215
|
+
</ul>
|
211
216
|
</div>
|
212
217
|
```
|
213
218
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
219
|
+
> [!TIP]
|
220
|
+
> You can also pass the component class as a string if your component class hasn't been defined yet. For example:
|
221
|
+
>
|
222
|
+
> ```ruby
|
223
|
+
> slot :header, "HeaderComponent"
|
224
|
+
> slot :item, "ItemComponent", collection: true
|
225
|
+
>```
|
218
226
|
|
219
|
-
# This will not work
|
220
|
-
slot :header, HeaderComponent # uninitialized constant BlogComponent::HeaderComponent
|
221
|
-
# You should do this
|
222
|
-
slot :header, "HeaderComponent"
|
223
227
|
|
224
|
-
|
228
|
+
## Lambda slot
|
225
229
|
|
226
|
-
|
227
|
-
# ...
|
228
|
-
end
|
229
|
-
end
|
230
|
-
```
|
230
|
+
Lambda slots are valuable when you prefer not to create another component for straightforward structures or when you need to render another component with specific parameters.
|
231
231
|
|
232
|
-
#### Lambda slots
|
233
|
-
Lambda slots are valuable when you prefer not to create another component for straightforward structures or when you need to render another view with specific parameters
|
234
232
|
```ruby
|
235
|
-
|
236
|
-
class BlogComponent < Phlex::HTML
|
233
|
+
class ListComponent < Phlex::HTML
|
237
234
|
include Phlex::Slotable
|
238
235
|
|
239
|
-
slot :header, ->(size:, &content)
|
240
|
-
|
241
|
-
end
|
236
|
+
slot :header, ->(size:, &content) do
|
237
|
+
render HeaderComponent.new(size: size, color: "primary")
|
238
|
+
end
|
239
|
+
slot :item, ->(href:, &content) { li { a(href: href, &content) } }, collection: true
|
242
240
|
|
243
|
-
class MyPage < Phlex::HTML
|
244
241
|
def template
|
245
|
-
|
246
|
-
|
242
|
+
div id: "header" do
|
243
|
+
render header_slot if header_slot?
|
244
|
+
end
|
247
245
|
|
248
|
-
|
249
|
-
|
250
|
-
blog.with_post { "Post C" }
|
246
|
+
ul do
|
247
|
+
item_slots.each { |slot| render slot }
|
251
248
|
end
|
252
249
|
end
|
253
250
|
end
|
254
|
-
```
|
255
|
-
|
256
|
-
You can access the internal view state within lambda slots. For example:
|
257
|
-
```ruby
|
258
|
-
class BlogComponent < Phlex::HTML
|
259
|
-
include Phlex::Slotable
|
260
251
|
|
261
|
-
|
252
|
+
ListComponent.new.call do |list|
|
253
|
+
list.with_header(size: "lg") { "Hello World!" }
|
262
254
|
|
263
|
-
|
264
|
-
|
265
|
-
|
255
|
+
list.with_item(href: "/a") { "Item A" }
|
256
|
+
list.with_item(href: "/b") { "Item B" }
|
257
|
+
list.with_item(href: "/c") { "Item C" }
|
266
258
|
end
|
259
|
+
```
|
267
260
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
261
|
+
Returning:
|
262
|
+
|
263
|
+
```html
|
264
|
+
<div id="header">
|
265
|
+
<h1 class="text-lg text-primary">Hello World!</h1>
|
266
|
+
|
267
|
+
<ul>
|
268
|
+
<li><a href="/a">Item A</a></li>
|
269
|
+
<li><a href="/b">Item B</a></li>
|
270
|
+
<li><a href="/c">Item C</a></li>
|
271
|
+
</ul>
|
272
|
+
</div>
|
275
273
|
```
|
276
274
|
|
277
|
-
|
278
|
-
|
275
|
+
> [!TIP]
|
276
|
+
> You can access the internal component state within lambda slots. For example
|
277
|
+
>
|
278
|
+
> ```ruby
|
279
|
+
> slot :header, ->(&content) { render HeaderComponent.new(featured: @featured), &content }
|
280
|
+
>
|
281
|
+
> def initialize(featured:)
|
282
|
+
> @featured = feature
|
283
|
+
> end
|
284
|
+
> ```
|
285
|
+
|
286
|
+
## Polymorphic slot
|
287
|
+
|
288
|
+
Polymorphic slots can render one of several possible slots, allowing for flexibility in component content. This feature is particularly useful when you require a fixed structure but need to accommodate different types of content. To implement this, simply pass a types hash containing the types along with corresponding slot definitions.
|
279
289
|
|
280
290
|
```ruby
|
291
|
+
class IconComponent < Phlex::HTML
|
292
|
+
# omitted code
|
293
|
+
end
|
294
|
+
|
295
|
+
class ImageComponent < Phlex::HTML
|
296
|
+
# omitted code
|
297
|
+
end
|
298
|
+
|
281
299
|
class CardComponent < Phlex::HTML
|
282
300
|
include Phlex::Slotable
|
283
301
|
|
@@ -285,73 +303,45 @@ class CardComponent < Phlex::HTML
|
|
285
303
|
|
286
304
|
def template
|
287
305
|
if avatar_slot?
|
288
|
-
|
289
|
-
|
306
|
+
div id: "avatar" do
|
307
|
+
render avatar_slot
|
290
308
|
end
|
291
309
|
end
|
292
310
|
end
|
293
311
|
end
|
294
|
-
```
|
295
312
|
|
296
|
-
|
297
|
-
|
298
|
-
class UserCardComponent < Phlex::HTML
|
299
|
-
def initialize(user:)
|
300
|
-
@user = user
|
301
|
-
end
|
313
|
+
User = Data.define(:image_url)
|
314
|
+
user = User.new(image_url: "user.png")
|
302
315
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
card.with_icon_avatar(name: :user)
|
309
|
-
end
|
310
|
-
end
|
316
|
+
CardComponent.new.call do |card|
|
317
|
+
if user.image_url
|
318
|
+
card.with_image_avatar(src: user.image_url)
|
319
|
+
else
|
320
|
+
card.with_icon_avatar(name: :user)
|
311
321
|
end
|
312
322
|
end
|
313
323
|
```
|
314
324
|
|
315
|
-
|
316
|
-
```ruby
|
317
|
-
class CardComponent < Phlex::HTML
|
318
|
-
include Phlex::Slotable
|
319
|
-
|
320
|
-
slot :avatar, types: {
|
321
|
-
icon: IconComponent,
|
322
|
-
image: "ImageComponent",
|
323
|
-
text: ->(size:, &content) { span(class: "text-#{size}", &content) }
|
324
|
-
}, many: true
|
325
|
-
|
326
|
-
def template
|
327
|
-
if avatar_slots?
|
328
|
-
avatar_slots.each do |slot|
|
329
|
-
render slot
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
span { "Count: #{avatar_slots.size}" }
|
334
|
-
end
|
325
|
+
Returning:
|
335
326
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
def template
|
341
|
-
render CardComponent.new do |card|
|
342
|
-
card.with_image_avatar(src: @user.image)
|
343
|
-
card.with_icon_avatar(name: :user)
|
344
|
-
card.with_text_avatar(size: :lg) { "SV" }
|
345
|
-
end
|
346
|
-
end
|
347
|
-
end
|
327
|
+
```html
|
328
|
+
<div id="avatar">
|
329
|
+
<img src="user.png"/>
|
330
|
+
</div>
|
348
331
|
```
|
349
332
|
|
333
|
+
Note that you need to use `with_{type}_{slot_name}` to set slot content. In the example above, it was used `with_image_avatar` and `with_icon_avatar`.
|
350
334
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
335
|
+
> [!TIP]
|
336
|
+
> You can take advantage of all the previously introduced features, such as lambda slot and slot collection:
|
337
|
+
>
|
338
|
+
> ```ruby
|
339
|
+
> slot :avatar, collection: true, types: {
|
340
|
+
> icon: IconComponent,
|
341
|
+
> image: "ImageComponent",
|
342
|
+
> text: ->(&content) { span(class: "avatar", &content) }
|
343
|
+
> }
|
344
|
+
> ```
|
355
345
|
|
356
346
|
## Development
|
357
347
|
|
@@ -361,7 +351,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
361
351
|
|
362
352
|
## Contributing
|
363
353
|
|
364
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/stephannv/phlex-
|
354
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/stephannv/phlex-slotable. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/stephannv/phlex-slotable/blob/master/CODE_OF_CONDUCT.md).
|
365
355
|
|
366
356
|
## License
|
367
357
|
|
data/benchmark/main.rb
CHANGED
data/lib/phlex/slotable.rb
CHANGED
@@ -9,35 +9,36 @@ module Phlex
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
|
-
def slot(slot_name, callable = nil, types: nil,
|
12
|
+
def slot(slot_name, callable = nil, types: nil, collection: false)
|
13
13
|
include Phlex::DeferredRender
|
14
14
|
|
15
15
|
if types
|
16
16
|
types.each do |type, callable|
|
17
|
-
define_setter_method(slot_name, callable,
|
17
|
+
define_setter_method(slot_name, callable, collection: collection, type: type)
|
18
18
|
end
|
19
19
|
else
|
20
|
-
define_setter_method(slot_name, callable,
|
20
|
+
define_setter_method(slot_name, callable, collection: collection)
|
21
21
|
end
|
22
|
-
define_predicate_method(slot_name,
|
23
|
-
define_getter_method(slot_name,
|
22
|
+
define_predicate_method(slot_name, collection: collection)
|
23
|
+
define_getter_method(slot_name, collection: collection)
|
24
24
|
end
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
-
def define_setter_method(slot_name, callable,
|
28
|
+
def define_setter_method(slot_name, callable, collection:, type: nil)
|
29
29
|
slot_name_with_type = type ? "#{type}_#{slot_name}" : slot_name
|
30
|
+
signature = callable.nil? ? "(&block)" : "(*args, **kwargs, &block)"
|
30
31
|
|
31
|
-
setter_method = if
|
32
|
+
setter_method = if collection
|
32
33
|
<<-RUBY
|
33
|
-
def with_#{slot_name_with_type}
|
34
|
+
def with_#{slot_name_with_type}#{signature}
|
34
35
|
@#{slot_name}_slots ||= []
|
35
36
|
@#{slot_name}_slots << #{callable_value(slot_name_with_type, callable)}
|
36
37
|
end
|
37
38
|
RUBY
|
38
39
|
else
|
39
40
|
<<-RUBY
|
40
|
-
def with_#{slot_name_with_type}
|
41
|
+
def with_#{slot_name_with_type}#{signature}
|
41
42
|
@#{slot_name}_slot = #{callable_value(slot_name_with_type, callable)}
|
42
43
|
end
|
43
44
|
RUBY
|
@@ -52,8 +53,8 @@ module Phlex
|
|
52
53
|
private :"__call_#{slot_name}__"
|
53
54
|
end
|
54
55
|
|
55
|
-
def define_getter_method(slot_name,
|
56
|
-
getter_method = if
|
56
|
+
def define_getter_method(slot_name, collection:)
|
57
|
+
getter_method = if collection
|
57
58
|
<<-RUBY
|
58
59
|
def #{slot_name}_slots
|
59
60
|
@#{slot_name}_slots ||= []
|
@@ -72,8 +73,8 @@ module Phlex
|
|
72
73
|
class_eval(getter_method, __FILE__, __LINE__ + 1)
|
73
74
|
end
|
74
75
|
|
75
|
-
def define_predicate_method(slot_name,
|
76
|
-
predicate_method = if
|
76
|
+
def define_predicate_method(slot_name, collection:)
|
77
|
+
predicate_method = if collection
|
77
78
|
<<-RUBY
|
78
79
|
def #{slot_name}_slots?
|
79
80
|
#{slot_name}_slots.any?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phlex-slotable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- stephann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: phlex
|