foundries 0.1.2 → 0.1.3

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: d9bda37a762c9a055ca42c5faa685e30a6201fbeccaa5bbb7adffa0ccaef3386
4
- data.tar.gz: 4fe49113055d53bb2e61df790fa037c849cff8d7b380011e6fd298fab0ec68af
3
+ metadata.gz: c8245b09fe2227ef4a25d5751c30f4a94a1d2d80519ef5fb97b8ba2b9dc527ef
4
+ data.tar.gz: 24162154115e9f413117fb88d71aa0cbc19374cbbf9b6fa059f23e36535511e5
5
5
  SHA512:
6
- metadata.gz: 6e2b1f8a7fbc9107f684883ae9435c8c6cfc004698f7a5316ec47fb3531b9d100be9b12b55a4c097cefbb48e871c653717dbdf4ed5733dcbaf1032f5fed6a8e0
7
- data.tar.gz: f25ae1307f8f675d4b6d617b13b9102639e49f29bd6f80f90145cc68023725a36eb3169207107c9af6cb1078188f8a0d104c6e591959fc1ee48d992563b9e827
6
+ metadata.gz: f0b22d20d6edc795ef1c7a2f3403b1a7e5cbbbc0d3ca4bd19fc82c25992bcea6d460175df202d8cd0465dd328a8bc189672171423ed283aa7879390450261318
7
+ data.tar.gz: 1ece80e18cdc964013db346ec665e2919f146bda411ddaf4254abb4c714c712a4a692cb30241a051da98029c164fbbc77b1e4fc44c2dac0cadda396c0fbccadf
data/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
+ ## [0.1.3] - 2026-03-13
9
+
10
+ ### Added
11
+
12
+ - ancestor DSL and ancestors_for for path-based hierarchy building (7027e06)
13
+
8
14
  ## [0.1.2] - 2026-03-12
9
15
 
10
16
  ### Added
@@ -18,21 +24,3 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
18
24
 
19
25
  - Collections initialize before blueprints (377632f)
20
26
  - Fix find parent scoping and collection_find_by kwargs handling (3ebfc3e)
21
-
22
- ## [0.1.1] - 2026-03-06
23
-
24
- ### Added
25
-
26
- - Blueprint base class with collection tracking, parent scoping, and factory_bot integration (0002336)
27
- - Snapshot caching system with Postgres and SQLite adapters for test suite acceleration (0002336)
28
- - Source file content hashing in snapshot fingerprint for automatic cache invalidation (cfb348d)
29
-
30
- ### Changed
31
-
32
- - Snapshot caching is opt-in via ARMATURE_CACHE=1 environment variable (0002336)
33
- - Similarity detection only warns on identical structure, not containment (a5bdf25)
34
-
35
- ### Fixed
36
-
37
- - Parentless blueprints no longer raise NameError when find calls same_parent? (cfb348d)
38
- - Snapshot-cached presets no longer produce false similarity warnings (a5bdf25)
@@ -200,6 +200,31 @@ module Foundries
200
200
  end
201
201
  alias_method :update_current, :load_state
202
202
 
203
+ # Build a hierarchy from a path string or array.
204
+ # Finds the blueprint that handles `type` and calls
205
+ # `ancestors` on it to recursively create the chain.
206
+ #
207
+ # ancestors_for :task, "org/block/template/phase/mod/event" do
208
+ # task "my_task"
209
+ # end
210
+ #
211
+ def ancestors_for(type, path = nil, path_arr: nil, &block)
212
+ path_arr ||= path.split("/")
213
+ blueprint_for(type).ancestors(path_arr, &block)
214
+ end
215
+
216
+ # Find the blueprint instance that handles a given method.
217
+ def blueprint_for(method_name)
218
+ resolved = self.class.aliases[method_name] || method_name
219
+ self.class.delegations.each do |klass, methods|
220
+ if methods.include?(resolved)
221
+ ivar = :"@#{ivar_name_for(klass)}"
222
+ return instance_variable_get(ivar)
223
+ end
224
+ end
225
+ raise "No blueprint handles :#{method_name}"
226
+ end
227
+
203
228
  private
204
229
 
205
230
  # Override in subclasses for post-initialize hooks (e.g. pending phase rules).
@@ -116,6 +116,23 @@ module Foundries
116
116
  @lookup_order = ancestors
117
117
  end
118
118
 
119
+ # Declare the ancestor type for path-based hierarchy
120
+ # creation via `ancestors_for`.
121
+ #
122
+ # ancestor :event
123
+ #
124
+ # Generates an `ancestors(path, &block)` method that
125
+ # pops the last path segment and either:
126
+ # - calls `foundry.send(type, name, &block)` if the
127
+ # path is empty (terminal)
128
+ # - calls `foundry.ancestors_for(type, ...)` to
129
+ # continue recursion otherwise
130
+ def ancestor(type = nil)
131
+ return @ancestor_type unless type
132
+
133
+ @ancestor_type = type
134
+ end
135
+
119
136
  # Declare which attributes are allowed through to factory_bot.
120
137
  def permitted_attrs(attr_list)
121
138
  define_method(:permitted_attrs) do |attrs|
@@ -208,6 +225,26 @@ module Foundries
208
225
  end
209
226
  end
210
227
 
228
+ # Walk a path array to build ancestor hierarchy, then
229
+ # yield the block in the innermost context. Requires
230
+ # the `ancestor` class DSL to be declared.
231
+ #
232
+ # ancestors(["org", "block", "template"], &block)
233
+ #
234
+ def ancestors(path, &block)
235
+ type = self.class.ancestor
236
+ raise "No ancestor declared for #{self.class}" unless type
237
+
238
+ name = path.pop
239
+ if path.empty?
240
+ foundry.send(type, name, &block)
241
+ else
242
+ foundry.ancestors_for(type, path_arr: path) do
243
+ foundry.send(type, name, &block)
244
+ end
245
+ end
246
+ end
247
+
211
248
  # Find or create: when no parent is present, walks ancestors
212
249
  # via lookup_order; otherwise finds from parent or creates.
213
250
  def find_or_create(name, attrs = {})
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Foundries
4
- VERSION = "0.1.2"
5
- RELEASE_DATE = "2026-03-12"
4
+ VERSION = "0.1.3"
5
+ RELEASE_DATE = "2026-03-13"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foundries
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Dowd