crumbly 2.1.0 → 2.2.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 +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +20 -3
- data/lib/crumbly/trail.rb +23 -2
- data/lib/crumbly/verifier.rb +2 -1
- data/lib/crumbly/version.rb +1 -1
- data/lib/crumbly/view_helpers.rb +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 06aa2669dc2486a8c255ca46215e1c65e7ca3eaf76cd834501a7c0f8a1734237
|
|
4
|
+
data.tar.gz: 37ab7df264cbb31555bc2f3e646c2ea10036057dac7e9f4f70e022506906f6cf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5d77cc663933f726c4923fb1a5655ecff481b0eaabb6bcc0fb852306bf342e7f7838d420a68b823234fe3a13d4ea40355a500bdce8e80dc86ecb0a24788b2dc9
|
|
7
|
+
data.tar.gz: 6d3a5af07dcd0d5e69b3a6d2f6669c03c4eae29d182a17d30fa69f8f24886afd67f27d2b89e5394561f166c4033d4166d792fb4f5acca46902290b7140e6bb27
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [2.2.0] — 2026-11-06
|
|
6
|
+
|
|
7
|
+
A trail class can turn off derived trails with `derive_trails false`, and a derived level labels a record without its own `to_s` "Invoice 12" instead of `#<Invoice:0x…>`.
|
|
8
|
+
|
|
9
|
+
**New**
|
|
10
|
+
- `derive_trails false` in a trail class, for apps that want only the trails they write, as with gretel: a view without a `breadcrumb` call gets an empty `breadcrumb_trail` and a nil `breadcrumb_json_ld`. Subclasses inherit it and `derive_trails true` turns it back on. In such a class, `Crumbly.verify!` reports a crumb that only a derived trail would read as unused, and `Crumbly::Oracle.redundant_calls` lists nothing.
|
|
11
|
+
|
|
12
|
+
**Fixed**
|
|
13
|
+
- A derived level whose record's model doesn't define `to_s` is labelled with the translated model name and id, "Invoice 12", instead of Ruby's `#<Invoice:0x000…>`. A model's own `to_s` still wins.
|
|
14
|
+
|
|
5
15
|
## [2.1.0] — 2026-11-06
|
|
6
16
|
|
|
7
17
|
Crumbs refuse `javascript:`, `vbscript:` and `data:` URLs, and a nil record, odd bytes or `=begin` comments no longer break Crumbly.
|
|
@@ -76,7 +86,8 @@ tests. Replaces gretel: `crumbly-convert` turns its breadcrumbs files into Crumb
|
|
|
76
86
|
`breadcrumb` calls a derived trail may now cover.
|
|
77
87
|
- `Crumbly::Oracle.compare` draws trails with gretel and with Crumbly, from a test of an app migrating.
|
|
78
88
|
|
|
79
|
-
[Unreleased]: https://github.com/levups/crumbly/compare/v2.
|
|
89
|
+
[Unreleased]: https://github.com/levups/crumbly/compare/v2.2.0...HEAD
|
|
90
|
+
[2.2.0]: https://github.com/levups/crumbly/compare/v2.1.0...v2.2.0
|
|
80
91
|
[2.1.0]: https://github.com/levups/crumbly/compare/v2.0.0...v2.1.0
|
|
81
92
|
[2.0.0]: https://github.com/levups/crumbly/compare/v1.1.0...v2.0.0
|
|
82
93
|
[1.1.0]: https://github.com/levups/crumbly/compare/v1.0.0...v1.1.0
|
data/README.md
CHANGED
|
@@ -169,13 +169,14 @@ When a view doesn't call `breadcrumb`, Crumbly builds the trail from the action:
|
|
|
169
169
|
| Action | Trail |
|
|
170
170
|
|---|---|
|
|
171
171
|
| `index` | the collection: your `posts` crumb if you wrote one, or else the model's plural name linked to the `index` route |
|
|
172
|
-
| `show` | the record: your `post` crumb, or else its
|
|
172
|
+
| `show` | the record: your `post` crumb, or else its label linked to the `show` route, under the collection |
|
|
173
173
|
| `new`, `create` | "New" under the collection |
|
|
174
174
|
| `edit`, `update` | "Edit" under the record |
|
|
175
175
|
|
|
176
176
|
The record is the one the controller has already loaded, `@post` in `PostsController`. Crumbly never runs a query
|
|
177
177
|
to find it. "New" and "Edit" come from the `crumbly.new` and `crumbly.edit` translations, so you can translate
|
|
178
|
-
them.
|
|
178
|
+
them. A record's label is its `to_s`. A model without a `to_s` of its own gets its translated model name and id
|
|
179
|
+
instead ("Post 5"), not `#<Post:0x000...>`.
|
|
179
180
|
|
|
180
181
|
Nested routes work too. On `/admin/posts/5/comments`, the trail is Posts › Post 5 › Comments, and the post is
|
|
181
182
|
the `@post` the controller loaded. If the controller didn't load it, Crumbly skips that level and keeps Posts.
|
|
@@ -183,6 +184,19 @@ the `@post` the controller loaded. If the controller didn't load it, Crumbly ski
|
|
|
183
184
|
To change how these trails are built, override the private methods `collection_crumb`, `record_crumb`,
|
|
184
185
|
`new_record_crumb` or `edit_record_crumb` in your trail class.
|
|
185
186
|
|
|
187
|
+
To turn them off, set `derive_trails false` in the trail class. A view that doesn't call `breadcrumb` then has no
|
|
188
|
+
trail, as with gretel: `breadcrumb_trail` returns `[]` and `breadcrumb_json_ld` returns `nil`.
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
module Admin
|
|
192
|
+
class Breadcrumbs < Crumbly::Trail
|
|
193
|
+
derive_trails false
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Subclasses inherit the setting, and `derive_trails true` turns it back on in one of them.
|
|
199
|
+
|
|
186
200
|
### Which crumb wins
|
|
187
201
|
|
|
188
202
|
Crumbly takes the first of these that applies:
|
|
@@ -194,6 +208,8 @@ Crumbly takes the first of these that applies:
|
|
|
194
208
|
3. The trail Crumbly works out. Its parent levels follow the same rule: your crumb for the parent's model if there
|
|
195
209
|
is one, or else a level Crumbly builds.
|
|
196
210
|
|
|
211
|
+
With `derive_trails false`, only the first applies.
|
|
212
|
+
|
|
197
213
|
## Testing your trails
|
|
198
214
|
|
|
199
215
|
Add one test:
|
|
@@ -218,7 +234,7 @@ fails when:
|
|
|
218
234
|
- a view or another crumb calls a crumb with the wrong number of arguments (calls spread over several lines, or
|
|
219
235
|
with a splat, are skipped);
|
|
220
236
|
- a crumb is never used. A crumb is used when another crumb, a view or a controller calls it, when a trail
|
|
221
|
-
Crumbly works out reads it, or when it is named after a model.
|
|
237
|
+
Crumbly works out reads it (unless its class sets `derive_trails false`), or when it is named after a model.
|
|
222
238
|
|
|
223
239
|
A crumb defined twice in the same class is caught even earlier: the class raises `Crumbly::DuplicateCrumb` when it
|
|
224
240
|
loads.
|
|
@@ -296,6 +312,7 @@ It prints each line it left out or couldn't convert exactly, and with `--views`,
|
|
|
296
312
|
Crumbly may now make unnecessary. It needs Prism 1.2 or later: Ruby 3.4 comes with it, and on Ruby 3.3 you add
|
|
297
313
|
`gem "prism"` to the development group. While gretel is still installed on the migration branch,
|
|
298
314
|
`Crumbly::Oracle` draws each trail your tests render with both gems and lists where the labels or URLs differ.
|
|
315
|
+
To keep gretel's empty trail on pages whose views name no crumb, set `derive_trails false` in the trail class.
|
|
299
316
|
|
|
300
317
|
The [migration guide](https://levups.github.io/crumbly/migration.html) has every step: what the converter maps to
|
|
301
318
|
what, what it leaves to you, the comparison in your tests, and the same walk-through for loaf and
|
data/lib/crumbly/trail.rb
CHANGED
|
@@ -37,6 +37,18 @@ module Crumbly
|
|
|
37
37
|
raise DuplicateCrumb, "#{self}##{name} is defined twice: the second definition would replace the first"
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def derive_trails(derive)
|
|
41
|
+
raise ArgumentError, "derive_trails takes true or false, not #{derive.inspect}" unless derive in true | false
|
|
42
|
+
|
|
43
|
+
@derive_trails = derive
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def derive_trails?
|
|
47
|
+
return @derive_trails unless @derive_trails.nil?
|
|
48
|
+
|
|
49
|
+
self == Trail || superclass.derive_trails?
|
|
50
|
+
end
|
|
51
|
+
|
|
40
52
|
def crumb?(name)
|
|
41
53
|
trail_class = self
|
|
42
54
|
while trail_class < Trail
|
|
@@ -52,6 +64,8 @@ module Crumbly
|
|
|
52
64
|
end
|
|
53
65
|
|
|
54
66
|
def derive(helpers)
|
|
67
|
+
return [] unless derive_trails?
|
|
68
|
+
|
|
55
69
|
new(helpers).send(:derived_levels)
|
|
56
70
|
end
|
|
57
71
|
end
|
|
@@ -196,7 +210,14 @@ module Crumbly
|
|
|
196
210
|
def record_crumb(record)
|
|
197
211
|
return crumb_for(record) if crumb_name_for(record)
|
|
198
212
|
|
|
199
|
-
crumb(record
|
|
213
|
+
crumb(record_label(record), route_path(action: "show", id: record), parent: collection_crumb)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Kernel#to_s would label the level "#<Invoice:0x000...>".
|
|
217
|
+
def record_label(record)
|
|
218
|
+
return record.to_s unless record.class.instance_method(:to_s).owner == Kernel && record.class.respond_to?(:model_name)
|
|
219
|
+
|
|
220
|
+
"#{record.model_name.human} #{record.to_param}"
|
|
200
221
|
end
|
|
201
222
|
|
|
202
223
|
def new_record_crumb
|
|
@@ -235,7 +256,7 @@ module Crumbly
|
|
|
235
256
|
return crumb_for(parent.record) if crumb_name_for(parent.record)
|
|
236
257
|
|
|
237
258
|
name = parent.name.pluralize
|
|
238
|
-
crumb(parent.record
|
|
259
|
+
crumb(record_label(parent.record), route_path(resources: name, action: "show", id: parent.id, **route_parent_ids(ancestors)),
|
|
239
260
|
parent: nested_collection_crumb(name, ancestors))
|
|
240
261
|
end
|
|
241
262
|
|
data/lib/crumbly/verifier.rb
CHANGED
|
@@ -165,8 +165,9 @@ module Crumbly
|
|
|
165
165
|
end
|
|
166
166
|
|
|
167
167
|
def dead_crumbs
|
|
168
|
-
|
|
168
|
+
reachable_names_with_derivation = called_names + derived_names
|
|
169
169
|
trail_classes.flat_map do |trail_class|
|
|
170
|
+
reachable_names = trail_class.derive_trails? ? reachable_names_with_derivation : called_names
|
|
170
171
|
dead_names = crumb_names(trail_class).reject do |name|
|
|
171
172
|
reachable_names.include?(name) || model_name?(name)
|
|
172
173
|
end
|
data/lib/crumbly/version.rb
CHANGED
data/lib/crumbly/view_helpers.rb
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Crumbly
|
|
4
4
|
module ViewHelpers
|
|
5
|
-
# The view names its crumb; a view that says nothing gets the trail derived from its controller and action
|
|
5
|
+
# The view names its crumb; a view that says nothing gets the trail derived from its controller and action,
|
|
6
|
+
# or none under `derive_trails false`.
|
|
6
7
|
def breadcrumb(target, *arguments)
|
|
7
8
|
@crumbly_breadcrumb = [target, arguments]
|
|
8
9
|
@crumbly_trail = nil
|