hibiki_rails 0.9.0 → 0.9.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8ac38db2808ab9f20f6fccf7cf50c202454fc222cba122f6466e25cf5fe2eb3
|
|
4
|
+
data.tar.gz: 89b5a3ab98b4bf10ba10466de9f352d9e9e3c3a814abb35175df798aa4fafc89
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d970c278b67be036e36a4703e3a38f6581b27bb890a4a7b599000755085a74f311646ae1519752e6457633590326bb9e6ca0fcf1b7fb1925e784d5f3a2c70b3
|
|
7
|
+
data.tar.gz: 468b0706478f48ee97019baf35b4da08912647b7a649575b8f970d05a21186cb85cf9c6c5dc89d9d0e6c75c6b0ad5c936c0b5cb6d8b223b5924edbb094ea2304
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ The gem and the npm package are released in lockstep and share these version
|
|
|
4
4
|
numbers — `app/assets/javascripts/hibiki.js` is a single copy served both ways,
|
|
5
5
|
so importmap and bundler apps always resolve identical client code.
|
|
6
6
|
|
|
7
|
+
## 0.9.1 — 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
**`hibiki:rails:nested` creates a missing child model from the field list.**
|
|
12
|
+
`bin/rails g hibiki:rails:nested Song Credit role:string position:integer`
|
|
13
|
+
no longer refuses when `Credit` doesn't exist: the generator invokes
|
|
14
|
+
`active_record:model` with `song:references` prepended (kept where you put it
|
|
15
|
+
if you typed it yourself), then wires the edge off the argument list exactly
|
|
16
|
+
as if the field list had narrowed an existing schema. Run
|
|
17
|
+
`bin/rails db:migrate` before using the fieldset. A created child is never
|
|
18
|
+
ordered silently — put `position` in the field list, or pass
|
|
19
|
+
`--position=COLUMN` and the column joins the create-table migration. With an
|
|
20
|
+
existing child model nothing changes, and a missing model with no field list
|
|
21
|
+
still refuses, now suggesting the inline syntax.
|
|
22
|
+
|
|
23
|
+
The runtime and the packaged client did not change; the npm 0.9.1 exists only
|
|
24
|
+
to keep the lockstep rule.
|
|
25
|
+
|
|
7
26
|
## 0.9.0 — 2026-08-17
|
|
8
27
|
|
|
9
28
|
### Added
|
|
@@ -8,9 +8,11 @@ Description:
|
|
|
8
8
|
fallback in the full-page form, and the controller's params.expect
|
|
9
9
|
double-array group.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
the
|
|
11
|
+
When the Child model exists (migrated, with belongs_to :<parent>), an
|
|
12
|
+
optional field list narrows or orders its form fields; the facts stay
|
|
13
|
+
the schema's. When it doesn't, the field list creates it — model and
|
|
14
|
+
migration via active_record:model, <parent>:references prepended for
|
|
15
|
+
you. Run bin/rails db:migrate before using the fieldset.
|
|
14
16
|
|
|
15
17
|
Depth is composition: run once per edge. A run whose Parent is itself a
|
|
16
18
|
nested child (its _<parent>_fields partial exists) nests into that
|
|
@@ -20,7 +22,8 @@ Description:
|
|
|
20
22
|
the fieldset ordered — the has_many gains an order scope, the parent
|
|
21
23
|
form stamps positions from array order, and rows get ↑/↓ buttons. The
|
|
22
24
|
named column is added by migration when missing; --skip-position opts
|
|
23
|
-
out entirely.
|
|
25
|
+
out entirely. A created child is never ordered silently: put position
|
|
26
|
+
in the field list, or pass --position.
|
|
24
27
|
|
|
25
28
|
Examples:
|
|
26
29
|
bin/rails g hibiki:rails:nested Song Credit
|
|
@@ -28,3 +31,5 @@ Examples:
|
|
|
28
31
|
bin/rails g hibiki:rails:nested Credit Contribution
|
|
29
32
|
|
|
30
33
|
bin/rails g hibiki:rails:nested Song Credit artist:references role:string --position=rank
|
|
34
|
+
|
|
35
|
+
bin/rails g hibiki:rails:nested Song Credit role:string position:integer
|
|
@@ -22,6 +22,8 @@ module Hibiki
|
|
|
22
22
|
# generic Hibiki::Rails::NestedActions), reactive_nested on the parent
|
|
23
23
|
# form, the model wiring, the classic fields_for fallback in the
|
|
24
24
|
# full-page form, and the controller's params.expect double-array group.
|
|
25
|
+
# A missing child model is created from the field list (model +
|
|
26
|
+
# migration via active_record:model, the parent reference prepended).
|
|
25
27
|
#
|
|
26
28
|
# Depth is composition — run once per edge. A run whose parent is
|
|
27
29
|
# itself a nested child injects into the parent's own fields partial
|
|
@@ -62,6 +64,14 @@ module Hibiki
|
|
|
62
64
|
warn_without_phlex_rails
|
|
63
65
|
end
|
|
64
66
|
|
|
67
|
+
def create_child_model
|
|
68
|
+
return unless create_child?
|
|
69
|
+
|
|
70
|
+
# to_argv, never GeneratedAttribute#to_s: `title:string!` round-trips
|
|
71
|
+
# through to_s as "title:string{null}", which .parse then rejects.
|
|
72
|
+
invoke "active_record:model", child_model_argv
|
|
73
|
+
end
|
|
74
|
+
|
|
65
75
|
def create_child_form
|
|
66
76
|
template "child_form.rb.tt", child_form_path
|
|
67
77
|
end
|
|
@@ -111,10 +121,7 @@ module Hibiki
|
|
|
111
121
|
end
|
|
112
122
|
|
|
113
123
|
def post_install
|
|
114
|
-
|
|
115
|
-
say_status :migrate, "#{child_table_name}.#{position_column} was added — " \
|
|
116
|
-
"run bin/rails db:migrate before using the fieldset.", :yellow
|
|
117
|
-
end
|
|
124
|
+
migrate_notice
|
|
118
125
|
schema.belongs_tos.each do |column|
|
|
119
126
|
say_status :assoc, "using #{column.association_class_name}##{column.label_column} as " \
|
|
120
127
|
"the #{column.human_name.downcase} option label — edit " \
|
|
@@ -124,6 +131,18 @@ module Hibiki
|
|
|
124
131
|
|
|
125
132
|
private
|
|
126
133
|
|
|
134
|
+
# Never both: a created child's ordering column rides its
|
|
135
|
+
# create-table migration.
|
|
136
|
+
def migrate_notice
|
|
137
|
+
if create_child?
|
|
138
|
+
say_status :migrate, "#{child_class_name} was generated — " \
|
|
139
|
+
"run bin/rails db:migrate before using the fieldset.", :yellow
|
|
140
|
+
elsif @position_migration
|
|
141
|
+
say_status :migrate, "#{child_table_name}.#{position_column} was added — " \
|
|
142
|
+
"run bin/rails db:migrate before using the fieldset.", :yellow
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
127
146
|
# The scaffold's own view layer, read from what it left on disk; an
|
|
128
147
|
# explicit --phlex wins. Deep mode reads it off the parent's fields
|
|
129
148
|
# partial instead of the row form.
|
|
@@ -36,8 +36,19 @@ module Hibiki
|
|
|
36
36
|
|
|
37
37
|
def child_form_class_name = "#{child_class_name}Form"
|
|
38
38
|
def child_form_path = File.join("app/forms", "#{child_class_name.underscore}_form.rb")
|
|
39
|
+
def child_model_path = File.join("app/models", "#{child_class_name.underscore}.rb")
|
|
39
40
|
def child_table_name = child_class_name.tableize.tr("/", "_")
|
|
40
41
|
|
|
42
|
+
# Create mode: no constant, no model file, and a field list to build
|
|
43
|
+
# from. Memoized before the invoke writes the file — later calls must
|
|
44
|
+
# keep the preflight answer.
|
|
45
|
+
def create_child?
|
|
46
|
+
return @create_child if defined?(@create_child)
|
|
47
|
+
|
|
48
|
+
@create_child = attributes.any? && child_class_name.safe_constantize.nil? &&
|
|
49
|
+
!exists?(child_model_path)
|
|
50
|
+
end
|
|
51
|
+
|
|
41
52
|
def child_class
|
|
42
53
|
@child_class ||= begin
|
|
43
54
|
klass = child_class_name.safe_constantize
|
|
@@ -53,9 +64,13 @@ module Hibiki
|
|
|
53
64
|
end
|
|
54
65
|
|
|
55
66
|
def missing_child_message
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
67
|
+
if exists?(child_model_path)
|
|
68
|
+
"#{child_class_name} has no table yet. Run bin/rails db:migrate first."
|
|
69
|
+
else
|
|
70
|
+
"No model #{child_class_name}. Pass its fields and the generator creates it " \
|
|
71
|
+
"(#{singular_name}:references is added for you):\n " \
|
|
72
|
+
"bin/rails g hibiki:rails:nested #{name} #{child} role:string"
|
|
73
|
+
end
|
|
59
74
|
end
|
|
60
75
|
|
|
61
76
|
# The child's belongs_to back to the parent. Required: the has_many's
|
|
@@ -92,9 +107,14 @@ module Hibiki
|
|
|
92
107
|
|
|
93
108
|
# Everything that can refuse, before anything is written.
|
|
94
109
|
def check_wireable!
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
if create_child?
|
|
111
|
+
check_parent_wireable!
|
|
112
|
+
check_creatable!
|
|
113
|
+
else
|
|
114
|
+
child_class
|
|
115
|
+
parent_reflection
|
|
116
|
+
check_parent_wireable!
|
|
117
|
+
end
|
|
98
118
|
check_editable_columns!
|
|
99
119
|
end
|
|
100
120
|
|
|
@@ -119,10 +139,21 @@ module Hibiki
|
|
|
119
139
|
|
|
120
140
|
raise ::Rails::Generators::Error,
|
|
121
141
|
"#{child_class_name} has no editable columns beyond " \
|
|
122
|
-
"#{
|
|
142
|
+
"#{child_foreign_key}#{" and #{position_column}" if ordered?} — " \
|
|
123
143
|
"nothing to build a fieldset from."
|
|
124
144
|
end
|
|
125
145
|
|
|
146
|
+
# A bare <parent>_id column generates no belongs_to, and the has_many's
|
|
147
|
+
# inverse_of and accepts_nested_attributes_for both stand on it.
|
|
148
|
+
def check_creatable!
|
|
149
|
+
fk = "#{singular_name}_id"
|
|
150
|
+
return if attributes.none? { !it.reference? && it.name == fk }
|
|
151
|
+
|
|
152
|
+
raise ::Rails::Generators::Error,
|
|
153
|
+
"Spell the parent column #{singular_name}:references — a bare #{fk} " \
|
|
154
|
+
"generates no belongs_to, and the nested wiring needs one."
|
|
155
|
+
end
|
|
156
|
+
|
|
126
157
|
# ---- the owning resource ---------------------------------------------
|
|
127
158
|
#
|
|
128
159
|
# Root mode: the parent itself. Deep mode: derived from where the
|
|
@@ -182,15 +213,36 @@ module Hibiki
|
|
|
182
213
|
|
|
183
214
|
# ---- the child schema ------------------------------------------------
|
|
184
215
|
#
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
216
|
+
# Introspection when the child model exists (the scaffold's 3.6 merge
|
|
217
|
+
# when a field list narrows or orders it); the argument-only path when
|
|
218
|
+
# this run is creating the model — the fresh constant is not loadable
|
|
219
|
+
# in-process, so nothing may read it. The parent's foreign key and the
|
|
220
|
+
# ordering column never become form fields: the association assigns
|
|
221
|
+
# one, the parent form stamps the other.
|
|
222
|
+
|
|
223
|
+
def introspectable_child = create_child? ? nil : child_class
|
|
224
|
+
|
|
225
|
+
# Argument-derived in create mode: there is no reflection to ask yet.
|
|
226
|
+
def child_foreign_key
|
|
227
|
+
@child_foreign_key ||= create_child? ? "#{singular_name}_id" : parent_reflection.foreign_key.to_s
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# What create_child_model hands to active_record:model: the parent
|
|
231
|
+
# reference prepended unless the field list already spells it, the
|
|
232
|
+
# --position column appended when ordering asked for one the list
|
|
233
|
+
# doesn't carry.
|
|
234
|
+
def child_model_argv
|
|
235
|
+
parent_ref = ("#{singular_name}:references" unless parent_ref_argument?)
|
|
236
|
+
position_arg = ("#{position_column}:integer" if ordered? && options[:position].present? &&
|
|
237
|
+
attributes.none? { it.name == position_column })
|
|
238
|
+
[child_class_name, *parent_ref, *attributes.map { to_argv(it) }, *position_arg]
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def parent_ref_argument? = attributes.any? { it.reference? && it.name == singular_name }
|
|
190
242
|
|
|
191
243
|
def full_schema
|
|
192
244
|
@full_schema ||= if attributes.any?
|
|
193
|
-
ScaffoldSchema.from_attributes(attributes, model:
|
|
245
|
+
ScaffoldSchema.from_attributes(attributes, model: introspectable_child)
|
|
194
246
|
else
|
|
195
247
|
ScaffoldSchema.from_model(child_class)
|
|
196
248
|
end
|
|
@@ -206,7 +258,7 @@ module Hibiki
|
|
|
206
258
|
|
|
207
259
|
def form_excluded?(column)
|
|
208
260
|
return true if column.belongs_to? && column.association_name == singular_name.to_sym
|
|
209
|
-
return true if column.name.to_s ==
|
|
261
|
+
return true if column.name.to_s == child_foreign_key
|
|
210
262
|
|
|
211
263
|
ordered? && column.name.to_s == position_column
|
|
212
264
|
end
|
|
@@ -218,6 +270,7 @@ module Hibiki
|
|
|
218
270
|
|
|
219
271
|
@ordered = if options[:skip_position] then false
|
|
220
272
|
elsif options[:position].present? then true
|
|
273
|
+
elsif create_child? then attributes.any? { it.name == "position" }
|
|
221
274
|
else child_class.column_names.include?("position")
|
|
222
275
|
end
|
|
223
276
|
end
|
|
@@ -225,7 +278,7 @@ module Hibiki
|
|
|
225
278
|
def position_column = @position_column ||= options[:position].presence || "position"
|
|
226
279
|
|
|
227
280
|
def position_migration_needed?
|
|
228
|
-
ordered? && !child_class.column_names.include?(position_column)
|
|
281
|
+
ordered? && !create_child? && !child_class.column_names.include?(position_column)
|
|
229
282
|
end
|
|
230
283
|
|
|
231
284
|
# ---- template refs ---------------------------------------------------
|
data/lib/hibiki/rails/version.rb
CHANGED