philiprehberger-multipart 0.6.0 → 0.7.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: 6f8a73fa59b67a22903e4c5e89acf357e638a5a9ccd352a2a20c08ae8b0b1b74
4
- data.tar.gz: 6185783dacffad0857177ac51b0e4f8d0ed3e1d288710be7003a4da39e192f91
3
+ metadata.gz: 52149f84f550056bd81cb48582d4f83ed2d4994367d3bfed999f73ed8ce84da7
4
+ data.tar.gz: c8be86b7ee7424e73729e0819ecff13caee6a585e733e9f4fd788056432af5a2
5
5
  SHA512:
6
- metadata.gz: d462b2a310a15bb9c36d90dacd45759c2ff6f44cb818e838938990e5c5ac9431a1d6d26e6945523a2dc0017e875693a6c84a81b1b1e6b90b8315bcdfd1f9d929
7
- data.tar.gz: d05baa1fcd1ee9f9ee0b0c6a795f694c6cd15574abee38700d5ec83471f8f27259de2ea2b9c6970baab5983e05449893d33a2705c7343f39200861c1d69b0ce2
6
+ metadata.gz: 2b733e65fbdf0f3431a766ca7d495f07d9512d996f405573dedcf1f033002b3a50cf289bc9648588b928ed72a1a5712232f071cb2cd32eafb07eec4546cdbc6e
7
+ data.tar.gz: 14ecdc2bb2269b7de32ce4203d5105fd83583466c229ca56574397e3f3d5922cbcde722e032967d269e4a7f1c3d9168379eecd16939168e5dd219f2134bb7cbb
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.0] - 2026-04-30
11
+
12
+ ### Added
13
+ - `Builder#size` — alias for `content_length`, matching the familiar Ruby `size` idiom
14
+ - `Builder#to_h` — structured `{ boundary:, parts: [...] }` summary of the builder for logging and debugging
15
+ - `Part#text?` — predicate, true when a part has no filename (inverse of `file?`)
16
+ - `Part#size` — byte size of the part's value
17
+
10
18
  ## [0.6.0] - 2026-04-20
11
19
 
12
20
  ### Added
data/README.md CHANGED
@@ -140,6 +140,25 @@ builder.part('avatar').content_type = 'image/webp'
140
140
  builder.part(:missing) # => nil
141
141
  ```
142
142
 
143
+ ### Inspecting the Builder
144
+
145
+ ```ruby
146
+ builder = Philiprehberger::Multipart.build do
147
+ field :name, 'Alice'
148
+ file :avatar, '/path/to/photo.png'
149
+ end
150
+
151
+ builder.size # => same as builder.content_length
152
+ builder.to_h
153
+ # => {
154
+ # boundary: "----PhiliprehbergerMultipart...",
155
+ # parts: [
156
+ # { name: "name", filename: nil, content_type: nil, size: 5 },
157
+ # { name: "avatar", filename: "photo.png", content_type: "image/png", size: 4096 }
158
+ # ]
159
+ # }
160
+ ```
161
+
143
162
  ### Custom Boundary
144
163
 
145
164
  ```ruby
@@ -167,6 +186,8 @@ builder.content_type # => "multipart/form-data; boundary=my-boundary"
167
186
  | `Builder#boundary` | The multipart boundary string |
168
187
  | `Builder#write_to(io)` | Stream the multipart body to an IO object |
169
188
  | `Builder#content_length` | Byte size of the body for Content-Length headers |
189
+ | `Builder#size` | Alias for `content_length` |
190
+ | `Builder#to_h` | Structured `{ boundary:, parts: [...] }` summary |
170
191
  | `Builder#headers` | Hash with Content-Type and Content-Length headers |
171
192
  | `Part#name` | The field name |
172
193
  | `Part#value` | The part value / body content |
@@ -174,6 +195,8 @@ builder.content_type # => "multipart/form-data; boundary=my-boundary"
174
195
  | `Part#filename` | The original filename (nil for text fields) |
175
196
  | `Part#content_type` | The MIME content type (nil for text fields) |
176
197
  | `Part#file?` | Whether this part is a file upload |
198
+ | `Part#text?` | Whether this part is a plain text field (inverse of `file?`) |
199
+ | `Part#size` | Byte size of the part's value |
177
200
 
178
201
  ## Development
179
202
 
@@ -123,6 +123,32 @@ module Philiprehberger
123
123
  size + "--#{@boundary}--\r\n".bytesize
124
124
  end
125
125
 
126
+ # Alias for {#content_length} matching the familiar Ruby `size` idiom.
127
+ #
128
+ # @return [Integer]
129
+ alias size content_length
130
+
131
+ # Inspect the builder state as a structured hash.
132
+ #
133
+ # Each entry in `:parts` summarizes a single part with its name,
134
+ # filename (or nil for text fields), content_type, and byte size.
135
+ # Useful for logging or debugging without dumping the full body.
136
+ #
137
+ # @return [Hash] `{ boundary:, parts: [{ name:, filename:, content_type:, size: }, ...] }`
138
+ def to_h
139
+ {
140
+ boundary: @boundary,
141
+ parts: @parts.map do |part|
142
+ {
143
+ name: part.name.to_s,
144
+ filename: part.filename,
145
+ content_type: part.content_type,
146
+ size: part.size
147
+ }
148
+ end
149
+ }
150
+ end
151
+
126
152
  # Return the headers hash for the request
127
153
  #
128
154
  # @return [Hash]
@@ -41,6 +41,20 @@ module Philiprehberger
41
41
  !@filename.nil?
42
42
  end
43
43
 
44
+ # Whether this part is a plain text field (not a file upload)
45
+ #
46
+ # @return [Boolean]
47
+ def text?
48
+ !file?
49
+ end
50
+
51
+ # Byte size of this part's value
52
+ #
53
+ # @return [Integer]
54
+ def size
55
+ @value.bytesize
56
+ end
57
+
44
58
  # Render this part as a multipart body segment
45
59
  #
46
60
  # @param boundary [String] the multipart boundary
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module Multipart
5
- VERSION = '0.6.0'
5
+ VERSION = '0.7.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-multipart
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-20 00:00:00.000000000 Z
11
+ date: 2026-05-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Build and parse multipart/form-data request bodies with a clean DSL for
14
14
  adding text fields and file uploads, including automatic MIME type detection, IO