phlex-slotable 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6daa3c251793367884c7260e217d1df50891db3e5e5d07d3510dce8dc9dab868
4
- data.tar.gz: 95a6c59d0c7571933821a8df89b76542789d16fe222677b7be48af06730bd7f1
3
+ metadata.gz: 47c3384e49460492a4ff914af1ecd7c6a16fa2841f90d49a4b83b84c305cf892
4
+ data.tar.gz: aed5afef686e5f630b98842de12b18cc9f5634dd9f099b07273a7aa281f2915a
5
5
  SHA512:
6
- metadata.gz: 1c04f7d85f3068f064d8b45566de267975cd73d86d5fe7b34114865836b8cdf064cc218f01c86ddc5ffce9b942d39b1ca63f4188af23222e86f4cd6570ad516b
7
- data.tar.gz: 14ac74deabd99d4af0b9370279bb0bf592d9116426c7037f40cee94c198f2d92a3dd034577218b6aaa0fa118cc7e54869966177ada7564ee96b00ca2d0e78687
6
+ metadata.gz: 02c8d0105b65526025feea5fe1aadd7851a96e8406ccb574c0b7bb45d732e54dc85c98f6fbb182af5f57ae8f404cbe17a879bafad42ef6ce9ecd0c168c286d75
7
+ data.tar.gz: 76a8bfd794fd7a7040bf1699db0dd3001f9d7de0cac0f641515494307a3cb370ab173588e2ba3610553c601f907d1da3990d5580702c1308c008e6d2ce11a327
data/.standard.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  # For available configuration options, see:
2
2
  # https://github.com/standardrb/standard
3
- ruby_version: 3.0
3
+ ruby_version: 3.3
4
+ format: progress
5
+ parallel: true
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.0] - 2024-02-14
4
+ - [BREAKING CHANGE] Rename `many` option to `collection`.
5
+
6
+ *stephannv*
7
+
8
+ - Improve generic slot performance
9
+
10
+ *stephannv*
11
+
12
+ ## [0.3.1] - 2024-02-14
13
+ - Support Ruby 2.7
14
+
15
+ *stephannv*
16
+
3
17
  ## [0.3.0] - 2024-02-14
4
18
 
5
19
  - Match Slotable peformance with DeferredRender
data/README.md CHANGED
@@ -2,10 +2,25 @@
2
2
  > Please note that Phlex::Slotable is currently under development and may undergo changes to its API before reaching the stable release (1.0.0). As a result, there may be breaking changes that affect its usage.
3
3
 
4
4
  # Phlex::Slotable
5
+ [![CI](https://github.com/stephannv/phlex-slotable/actions/workflows/main.yml/badge.svg)](https://github.com/stephannv/phlex-slotable/actions/workflows/main.yml)
5
6
 
6
7
  Phlex::Slotable enables slots feature to [Phlex](https://www.phlex.fun/) views. Inspired by ViewComponent.
7
8
 
8
- ## Installation
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
9
24
 
10
25
  Install the gem and add to the application's Gemfile by executing:
11
26
 
@@ -15,268 +30,272 @@ If bundler is not being used to manage dependencies, install the gem by executin
15
30
 
16
31
  $ gem install phlex-slotable
17
32
 
18
- ## Usage
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
+ ```
19
45
 
20
- #### Basic
46
+ Below, you will find a more detailed explanation of how to use the `slot` API.
21
47
 
22
- To incorportate slots into your Phlex views, include `Phlex::Slotable` and utilize `slot` class method to define them.
48
+ ## Generic slot
23
49
 
24
- - `slot :slot_name` declaration establishes a single slot intended for rendering once within a view
25
- - `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:
26
51
 
27
52
  ```ruby
28
- class BlogComponent < Phlex::HTML
53
+ class PageComponent < Phlex::HTML
29
54
  include Phlex::Slotable
30
55
 
31
- slot :header
32
- slot :post, many: true
33
-
34
- # ...
56
+ slot :title
35
57
  end
36
58
  ```
37
59
 
38
- To render a single slot, utilize the `{slot_name}_slot` method. For example, you can render the `header_slot` using `render header_slot`.
39
-
40
- 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`:
41
61
 
42
62
  ```ruby
43
- class BlogComponent < Phlex::HTML
63
+ class PageComponent < Phlex::HTML
44
64
  include Phlex::Slotable
45
65
 
46
- slot :header
47
- slot :post, many: true
66
+ slot :title
48
67
 
49
68
  def template
50
- div id: "header" do
51
- render header_slot
52
- end
69
+ header { render title_slot }
70
+ end
71
+ end
72
+ ```
53
73
 
54
- div id: "main" do
55
- post_slots.each do |slot|
56
- p { render slot }
57
- end
74
+ To pass content to the component's slot, you should use `with_{slot_name}`:
58
75
 
59
- span { "Count: #{post_slots.count}" }
60
- end
76
+ ```ruby
77
+ PageComponent.new.call do |page|
78
+ page.with_title do
79
+ h1 { "Hello World!" }
61
80
  end
62
81
  end
63
82
  ```
64
83
 
65
- When setting slot content, ensure to utilize the `with_{slot_name}` method while rendering the view:
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:
66
93
 
67
94
  ```ruby
68
- class MyPage < Phlex::HTML
69
- def template
70
- render BlogComponent.new do |blog|
71
- blog.with_header do
72
- h1 { "Hello World!" }
73
- end
95
+ class PageComponent < Phlex::HTML
96
+ include Phlex::Slotable
97
+
98
+ slot :title
74
99
 
75
- blog.with_post { "Post A" }
76
- blog.with_post { "Post B" }
77
- blog.with_post { "Post C" }
100
+ def template
101
+ if header_slot?
102
+ header { render title_slot }
103
+ else
104
+ plain "No title"
78
105
  end
79
106
  end
80
107
  end
81
-
82
- MyPage.new.call
83
108
  ```
84
109
 
85
- This will output:
110
+ ## Slot collection
86
111
 
87
- ```html
88
- <div id="header">
89
- <h1>Hello World</h1>
90
- </div>
91
- <div id="main">
92
- <p>Post A</p>
93
- <p>Post B</p>
94
- <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:
95
113
 
96
- <span>Count: 3</span>
97
- </div>
98
- ```
114
+ ```ruby
115
+ class ListComponent < Phlex::HTML
116
+ include Phlex::Slotable
99
117
 
100
- #### Predicate methods
118
+ slot :item, collection: true
119
+ end
120
+ ```
101
121
 
102
- You can verify whether a slot has been provided to the view using `{slot_name}_slot?` for single slots or `{slot_name}_slots?` when for multi-slots.
122
+ To render a collection of slots, iterate over the `{slot_name}_slots` collection and render each slot individually:
103
123
 
104
124
  ```ruby
105
- class BlogComponent < Phlex::HTML
106
- include Phlex::Slotable
125
+ class ListComponent < Phlex::HTML
126
+ include Phlex::Slotable
107
127
 
108
- slot :header
109
- slot :post, many: true
128
+ slot :item, collection: true
110
129
 
111
130
  def template
112
- if header_slot?
113
- div id: "header" do
114
- render header_slot
115
- end
116
- end
117
-
118
- div id: "main" do
119
- if post_slots?
120
- post_slots.each do |slot|
121
- p { render slot }
131
+ if item_slots?
132
+ ul do
133
+ item_slots.each do |item_slot|
134
+ li { render item_slot }
122
135
  end
123
-
124
- span { "Count: #{post_slots.count}" }
125
- else
126
- span { "No post yet" }
127
136
  end
128
137
  end
138
+
139
+ span { "Total: #{item_slots.size}" }
129
140
  end
130
141
  end
131
142
  ```
132
143
 
133
- #### View slot
134
-
135
- 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:
136
145
 
137
146
  ```ruby
138
- class HeaderComponent < Phlex::HTML
139
- def initialize(size:)
140
- @size = size
141
- end
142
-
143
- def template(&content)
144
- h1(class: "text-#{@size}", &content)
145
- 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" }
146
151
  end
152
+ ```
147
153
 
148
- class PostComponent < Phlex::HTML
149
- def initialize(featured:)
150
- @featured = featured
151
- end
154
+ Returning:
152
155
 
153
- def template(&content)
154
- p(class: @featured ? "featured" : nil, &content)
155
- end
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
156
173
  end
157
174
 
158
- class BlogComponent < Phlex::HTML
175
+ class ListItemComponent < Phlex::HTML
176
+ # omitted code
177
+ end
178
+
179
+ class ListComponent < Phlex::HTML
159
180
  include Phlex::Slotable
160
181
 
161
- slot :header, HeaderComponent
162
- slot :post, PostComponent, many: true
182
+ slot :header, ListHeaderComponent
183
+ slot :item, ListItemComponent, collection: true
163
184
 
164
185
  def template
165
- if header_slot?
166
- div id: "header" do
167
- render header_slot
168
- end
186
+ div id: "header" do
187
+ render header_slot if header_slot?
169
188
  end
170
189
 
171
- div id: "main" do
172
- if post_slots?
173
- post_slots.each { render slot }
174
-
175
- span { "Count: #{post_slots.count}" }
176
- else
177
- span { "No post yet" }
178
- end
190
+ ul do
191
+ item_slots.each { |slot| render slot }
179
192
  end
180
193
  end
181
194
  end
182
195
 
183
- class MyPage < Phlex::HTML
184
- def template
185
- render BlogComponent.new do |blog|
186
- blog.with_header(size: :lg) { "Hello World!" }
196
+ ListComponent.new.call do |list|
197
+ list.with_header(size: "lg") { "Hello World!" }
187
198
 
188
- blog.with_post(featured: true) { "Post A" }
189
- blog.with_post { "Post B" }
190
- blog.with_post { "Post C" }
191
- end
192
- end
199
+ list.with_item(active: true) { "Item A" }
200
+ list.with_item { "Item B" }
201
+ list.with_item { "Item C" }
193
202
  end
194
-
195
- MyPage.new.call
196
203
  ```
197
204
 
198
- The output:
205
+ Returning:
199
206
 
200
207
  ```html
201
208
  <div id="header">
202
- <h1 class="text-lg">Hello World</h1>
203
- </div>
204
- <div id="main">
205
- <p class="featured">Post A</p>
206
- <p>Post B</p>
207
- <p>Post C</p>
209
+ <h1 class="text-lg">Hello World!</h1>
208
210
 
209
- <span>Count: 3</span>
211
+ <ul>
212
+ <li class="active">Item A</li>
213
+ <li>Item B</li>
214
+ <li>Item C</li>
215
+ </ul>
210
216
  </div>
211
217
  ```
212
218
 
213
- You can pass the class name as a string for cases where the class isn't evaluated yet, such as with inner classes. For example:
214
- ```ruby
215
- class BlogComponent < Phlex::HTML
216
- include Phlex::Slotable
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
+ >```
217
226
 
218
- # This will not work
219
- slot :header, HeaderComponent # uninitialized constant BlogComponent::HeaderComponent
220
- # You should do this
221
- slot :header, "HeaderComponent"
222
227
 
223
- private
228
+ ## Lambda slot
224
229
 
225
- class HeaderComponent < Phlex::HTML
226
- # ...
227
- end
228
- end
229
- ```
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.
230
231
 
231
- #### Lambda slots
232
- 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
233
232
  ```ruby
234
-
235
- class BlogComponent < Phlex::HTML
233
+ class ListComponent < Phlex::HTML
236
234
  include Phlex::Slotable
237
235
 
238
- slot :header, ->(size:, &content) { render HeaderComponent.new(size: size, color: "blue"), &content }
239
- slot :post, ->(featured:, &content) { span(class: featured ? "featured" : nil, &content) }, many: true
240
- 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
241
240
 
242
- class MyPage < Phlex::HTML
243
241
  def template
244
- render BlogComponent.new do |blog|
245
- blog.with_header(size: :lg) { "Hello World!" }
242
+ div id: "header" do
243
+ render header_slot if header_slot?
244
+ end
246
245
 
247
- blog.with_post(featured: true) { "Post A" }
248
- blog.with_post { "Post B" }
249
- blog.with_post { "Post C" }
246
+ ul do
247
+ item_slots.each { |slot| render slot }
250
248
  end
251
249
  end
252
250
  end
253
- ```
254
-
255
- You can access the internal view state within lambda slots. For example:
256
- ```ruby
257
- class BlogComponent < Phlex::HTML
258
- include Phlex::Slotable
259
251
 
260
- slot :header, ->(size:, &content) { render HeaderComponent.new(size: size, color: @header_color), &content }
252
+ ListComponent.new.call do |list|
253
+ list.with_header(size: "lg") { "Hello World!" }
261
254
 
262
- def initialize(header_color:)
263
- @header_color = header_color
264
- end
255
+ list.with_item(href: "/a") { "Item A" }
256
+ list.with_item(href: "/b") { "Item B" }
257
+ list.with_item(href: "/c") { "Item C" }
265
258
  end
259
+ ```
266
260
 
267
- class MyPage < Phlex::HTML
268
- def template
269
- render BlogComponent.new(header_color: "red") do |blog|
270
- blog.with_header(size: :lg) { "Hello World!" }
271
- end
272
- end
273
- end
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>
274
273
  ```
275
274
 
276
- #### Polymorphic slots
277
- 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.
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.
278
289
 
279
290
  ```ruby
291
+ class IconComponent < Phlex::HTML
292
+ # omitted code
293
+ end
294
+
295
+ class ImageComponent < Phlex::HTML
296
+ # omitted code
297
+ end
298
+
280
299
  class CardComponent < Phlex::HTML
281
300
  include Phlex::Slotable
282
301
 
@@ -284,73 +303,45 @@ class CardComponent < Phlex::HTML
284
303
 
285
304
  def template
286
305
  if avatar_slot?
287
- figure id: "avatar" do
288
- render avatar_slot
306
+ div id: "avatar" do
307
+ render avatar_slot
289
308
  end
290
309
  end
291
310
  end
292
311
  end
293
- ```
294
312
 
295
- This allows you to set the icon slot using `with_icon_avatar` or the image slot using `with_image_avatar`:
296
- ```ruby
297
- class UserCardComponent < Phlex::HTML
298
- def initialize(user:)
299
- @user = user
300
- end
313
+ User = Data.define(:image_url)
314
+ user = User.new(image_url: "user.png")
301
315
 
302
- def template
303
- render CardComponent.new do |card|
304
- if @user.image?
305
- card.with_image_avatar(src: @user.image)
306
- else
307
- card.with_icon_avatar(name: :user)
308
- end
309
- 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)
310
321
  end
311
322
  end
312
323
  ```
313
324
 
314
- Please note that you can still utilize the other slot definition APIs:
315
- ```ruby
316
- class CardComponent < Phlex::HTML
317
- include Phlex::Slotable
318
-
319
- slot :avatar, types: {
320
- icon: IconComponent,
321
- image: "ImageComponent",
322
- text: ->(size:, &content) { span(class: "text-#{size}", &content) }
323
- }, many: true
324
-
325
- def template
326
- if avatar_slots?
327
- avatar_slots.each do |slot|
328
- render slot
329
- end
330
- end
331
-
332
- span { "Count: #{avatar_slots.size}" }
333
- end
325
+ Returning:
334
326
 
335
- ...
336
- end
337
-
338
- class UsersCardComponent < Phlex::HTML
339
- def template
340
- render CardComponent.new do |card|
341
- card.with_image_avatar(src: @user.image)
342
- card.with_icon_avatar(name: :user)
343
- card.with_text_avatar(size: :lg) { "SV" }
344
- end
345
- end
346
- end
327
+ ```html
328
+ <div id="avatar">
329
+ <img src="user.png"/>
330
+ </div>
347
331
  ```
348
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`.
349
334
 
350
- ## Roadmap
351
- - ~~Accept Strings as view class name~~
352
- - ✅ ~~Allow lambda slots~~
353
- - ✅ ~~Allow polymorphic slots~~
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
+ > ```
354
345
 
355
346
  ## Development
356
347
 
@@ -360,7 +351,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
360
351
 
361
352
  ## Contributing
362
353
 
363
- Bug reports and pull requests are welcome on GitHub at https://github.com/stephannv/phlex-slot. 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).
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).
364
355
 
365
356
  ## License
366
357
 
data/benchmark/main.rb CHANGED
@@ -34,7 +34,7 @@ class SlotableList < Phlex::HTML
34
34
  include Phlex::Slotable
35
35
 
36
36
  slot :header
37
- slot :item, many: true
37
+ slot :item, collection: true
38
38
 
39
39
  def template
40
40
  if header_slot
@@ -102,4 +102,5 @@ puts
102
102
  Benchmark.ips do |x|
103
103
  x.report("Deferred") { DeferredListExample.new.call }
104
104
  x.report("Slotable") { SlotableListExample.new.call }
105
+ x.compare!
105
106
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Slotable
5
- VERSION = "0.3.0"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
@@ -9,35 +9,36 @@ module Phlex
9
9
  end
10
10
 
11
11
  module ClassMethods
12
- def slot(slot_name, callable = nil, types: nil, many: false)
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, many: many, type: type)
17
+ define_setter_method(slot_name, callable, collection: collection, type: type)
18
18
  end
19
19
  else
20
- define_setter_method(slot_name, callable, many: many)
20
+ define_setter_method(slot_name, callable, collection: collection)
21
21
  end
22
- define_predicate_method(slot_name, many: many)
23
- define_getter_method(slot_name, many: many)
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, many:, type: nil)
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 many
32
+ setter_method = if collection
32
33
  <<-RUBY
33
- def with_#{slot_name_with_type}(*args, **kwargs, &block)
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}(*args, **kwargs, &block)
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, many:)
56
- getter_method = if many
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 ||= []
@@ -62,7 +63,9 @@ module Phlex
62
63
  RUBY
63
64
  else
64
65
  <<-RUBY
65
- def #{slot_name}_slot = @#{slot_name}_slot
66
+ def #{slot_name}_slot
67
+ @#{slot_name}_slot
68
+ end
66
69
  private :#{slot_name}_slot
67
70
  RUBY
68
71
  end
@@ -70,15 +73,19 @@ module Phlex
70
73
  class_eval(getter_method, __FILE__, __LINE__ + 1)
71
74
  end
72
75
 
73
- def define_predicate_method(slot_name, many:)
74
- predicate_method = if many
76
+ def define_predicate_method(slot_name, collection:)
77
+ predicate_method = if collection
75
78
  <<-RUBY
76
- def #{slot_name}_slots? = #{slot_name}_slots.any?
79
+ def #{slot_name}_slots?
80
+ #{slot_name}_slots.any?
81
+ end
77
82
  private :#{slot_name}_slots?
78
83
  RUBY
79
84
  else
80
85
  <<-RUBY
81
- def #{slot_name}_slot? = !#{slot_name}_slot.nil?
86
+ def #{slot_name}_slot?
87
+ !#{slot_name}_slot.nil?
88
+ end
82
89
  private :#{slot_name}_slot?
83
90
  RUBY
84
91
  end
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.3.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-14 00:00:00.000000000 Z
11
+ date: 2024-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex