Repository navigation
Since #294 a single date column stops the spinel emit, and --allow-unsupported does not write the tree as the error says #303
Description
Activity
Follow-up after reading
docs/guide/transpile.md, which documents this as intended: Spinel and the other non-rubytargets "reject Date at the project boundary before emitting files, even with--allow-unsupported". Thanks, that settles the boundary itself. Three questions so I can plan around it:- Is a date-only runtime for the Spinel target planned? If it is on the roadmap, I'll wait for it. If nobody has it scheduled, I'd be glad to contribute it. A pointer to the contract the
rubytarget's date-only adapter follows, and to the tests a Spinel version would have to pass, would be enough to start on a PR. - Is there an interim you'd accept for apps whose date columns are never read by the code they compile? For example, an explicit opt-in that keeps the pre-Meta PR: enum/Date semantics, relation finders, test typing, Alba ledger and CI #294 timestamp mapping for Spinel. If it is not wanted, I'll handle it on my side.
- The error message. It still ends with "rerun with --allow-unsupported to write the output anyway", which the boundary never honours. Would you take a small PR that drops that hint for this error?
Found while compiling a Rails API app with
--target spinel.- Is a date-only runtime for the Spinel target planned? If it is on the roadmap, I'll wait for it. If nobody has it scheduled, I'd be glad to contribute it. A pointer to the contract the
@thomasklemm, you shaped this boundary in #231/#294, so you're probably the best person to answer the questions above. The short version: is a date-only runtime for the Spinel target planned? If not, would you accept one as a contribution (a plain-Ruby date-only class in the Spinel runtime that meets the same contract as the
rubytarget's adapter)? Or would you rather Spinel ship adatepackage first? I'm happy to do the work either way. I'd just like to build it the way you'd want to merge it.@eddygarcas Very flexible on this. Feel free to move this in any direction you see fit when pairing with your agent and explore what's best. Guess the solution might also change over time as both roundhouse and spinel move along and mature
Reacted by Eduard G.Castelló@eddygarcas Following up with a bit more of what I found, since you asked which way I'd want this built. Still flexible on the shape. This is context, not a spec.
Thanks for the careful repro, and for checking the guide before treating the boundary as a bug. The refusal itself is the boundary from #294, and your fixture is enough to hit it:
reject_unsupported_datesinsrc/project.rskeys off the schema, so an unreadt.datecolumn rejects the Spinel project before any method is looked at.--allow-unsupportedonly downgrades diagnostics insrc/bin/roundhouse.rs. This gate returns an error fromtarget_filesbefore any file exists, which is why the run prints the hint and then exits 1 with nothing written. The guide already says that. The hint is the part that doesn't match.On your three questions, as I see them today:
-
I don't know of a date-only Spinel runtime on our side, and upstream doesn't look close either. Current
matz/spinelhas nopackages/date.docs/require.mdstill usesrequire "date"as the example of a require Spinel cannot satisfy, and matz/spinel#1102 is closed as out of scope. MatheusRich asked on 2026-10-01 whether to reopen it, now that other stdlib packages exist. No reply, and no package. CRuby'sdateis still the C extension (on the order of ten thousand lines). The pure-Ruby rewrite, ruby/date#155, is a similar size. So a fulldatepackage would be a real upstream project, not a missing method, and I wouldn't wait on it for this issue. If you also want to nudge that conversation upstream, that's welcome. It just doesn't unblock the apps you're compiling.What did land, and what makes a contribution here realistic, is matz/spinel#6399. Spinel now compiles a program-defined
class Dateinstead of treating it as a reopening of a builtin it doesn't have. A bounded date in our Spinel runtime looks like the practical path. How you lay that out is up to you: one class, a tiny local package, whatever fits the runtime you find. I'd rather it not claim to be the stdlib, andrequire "date"in emitted Spinel code will still fail the require gate, so the overlay file that already callsDate.iso8601can't be copied over as-is. It lives inruntime/spinel/scaffold/ruby_overlay/and is documented as CRuby/JRuby-only. -
An opt-in that puts the old timestamp mapping back is the one direction I'd rather we didn't take, even for columns nothing reads.
Ty::Dateexists so a date isn't quietly aTimeor aString. A clock and a zone the column doesn't have is the mixup Meta PR: enum/Date semantics, relation finders, test typing, Alba ledger and CI #294 closed. Supporting the column properly makes that opt-in unnecessary, including for the unread-column case in your fixture. If you find a narrower interim that stays honest, I'm open to it. -
Yes. The "rerun with --allow-unsupported" line is misleading for this error, and a small PR that drops the hint here is welcome on its own. It doesn't have to wait for the runtime.
The behavior we already promise on native Ruby, and that I'd hope a Spinel version agrees with, is pinned by
tests/date_columns_runtime.rb(run fromtests/emit_and_run.rs):- storage stays
YYYY-MM-DD, with no clock and no zone parse_db_date/format_db_dateare the seam (temporal_seaminsrc/lower/model_to_library/schema.rs)- SQL NULL, and the adapter's empty string for NULL, both come back as
nil >>/<<are calendar shifts, clamped once at month end (2024-01-31 >> 1is2024-02-29,>> 2is2024-03-31)- a shift doesn't mutate the receiver, and an index shift doesn't mutate storage
- JSON is the ISO date, or JSON
null, not a zoned timestamp 2023-02-29raises. A non-date write raisesTypeError- changing the zone doesn't move the calendar day
The analyzer already accepts a bounded surface, pinned in
tests/date_columns.rs:new/civil/parse/strptime/iso8601/today,>>/<<,to_date/to_time, the calendar components,iso8601/to_s/strftime, comparisons,leap?, and the weekday predicates. Known-bad arguments stay errors, andTimedoesn't gain>>.Scheduling::Dateis a different nominal class, notTy::Date. Outside that table, a call is still an analysis error, which is the right edge until there's a body for it. You don't have to grow the table to match whatever the new class can do.One project rule that's worth keeping in view: dropping the diagnostic is a claim that the emitted program runs, not just that
checkis quiet. The Ruby runtime test above is the kind of pin that makes that claim. How you arrange the Spinel run is your call.A few edges I noticed while reading, none of them executed, because the gate returns before emit. Worth a look when the boundary opens, and the fix shape is yours:
encoded_valueinsrc/lower/as_json_writer.rssends a date column throughJsonBuilder.encode_datetime. The specializedDateColumnpath in the same file already formats an ISO date. The unspecialized writer doesn't. From the primitive, a 10-character date looks like it would be quoted as raw text rather than given a clock, but I haven't run it.schema_time_columnslistsDateTimeandTime, notDate._as_json_onlywould then emit the stored text from[]. Rails' answer foras_json(only:)on a date is the ISO date ornull.attributesstaying stored text is intentional, and the runtime test pins that. I wouldn't change that one.- The jbuilder lowerer routes a date column through
encode_datetimeon<col>_raw, same as a timestamp. A date probably shouldn't grow aTand aZ.
Also separate from a first runtime, and fine to leave diagnosed rather than stubbed: ActiveSupport date extensions (
beginning_of_month,advance, and the rest of theTimetable),form.date_field/date_select(typed as strings, but not in the form-builder lowering table; I haven't emitted a view), andwhere(due_on: some_date). I didn't find a date-predicate fold. If a query can't be emitted as a comparison againstYYYY-MM-DDtext, I'd rather it diagnose than bind the value as a timestamp. Schema defaults likedefault: Date.current, and nonliteral strict-local defaults, are an existing ingestion gap. And arequire "date"in the app under compilation is still Spinel's refusal. Rewriting that into our class would be claiming the stdlib loaded.JRuby is the same project-boundary rejection, and the guide says its adapter path is unverified. I wouldn't mark JRuby, Roda, or the non-Ruby targets supported because Spinel grew a class. Each of those needs its own runtime.
If you take this on, I'm glad to review. The Ruby runtime test is the acceptance check I'd trust. The hint fix can land first, on its own, whenever you like.
Reacted by Eduard G.Castelló-
Thanks for the map, @thomasklemm. The hint fix is up on its own as #410. It stops suggesting
--allow-unsupportedwhenevertarget_filesrefuses the project, with no special case for Date. I'll start on the date-only Spinel runtime next, beginning with the JSON paths, and keeptests/date_columns_runtime.rbas the acceptance check.- added 2 commits that reference this issue
on Oct 4, 2026 - added a commit that references this issue
on Oct 5, 2026 - added 5 commits that reference this issue
on Oct 5, 2026 Spinel date-only runtime work is stacking on Hill climb #451 (bounded program-defined
Date, load only when the app uses dates so Campfire stays safe; hint half already merged as #410). Remaining edges (AS date extensions, form helpers, schemaDate.currentdefaults, other targets) stay ledgered — not claiming this issue fully closed until those are honest or explicitly out of scope.Update: Spinel Date / remaining #303 work is owned by #423 (
Add bounded Date runtime for Spinel), not Hill-climb #451.Early Date commits may still appear in #451’s history; do not stack further Date work on #451. Deferred Date ledger (AS date extensions, form date helpers, schema
Date.currentdefaults,require "date"as stdlib, non-Spinel date runtimes, matz/spinel#7334, Campfire omit-Date verification) → track against #423.13 remaining items
- added 13 commits that reference this issue
on Oct 5, 2026 - added a commit that references this issue
on Oct 6, 2026 Checked on main 37bb4c5: with #454 merged, the original repro (an app with a single
t.datecolumn) now emits for--target spinelwith exit 0. I'll leave this issue open or closed as you prefer, @thomasklemm, since you're tracking the remaining Date items (ActiveSupport extensions, form helpers, schema defaults) against #454.
Probed at main e5f8dd3, Linux x86-64.
Since #294 (which carries #231, "Preserve date-only columns in the native Ruby target"), an app with a single
t.datecolumn no longer emits for--target spinelat all, and--allow-unsupporteddoes not change that, although the error says it would.db/schema.rb:(plus a
Widgetmodel and aWidgetsController#indexthat rendersWidget.count; nothing reads the date column).--target spinel --allow-unsupportedon this fixtureI understand the boundary is deliberate (the PR says so for JRuby, Spinel and Roda). The two things that look unintended: the
--allow-unsupportedhint is not honoured, and an app whose date columns are never read by the code paths it compiles loses the target entirely, where before the tree was written and built (I did not check how fc49a94 typed the column). A per-column gap (or the old mapping under--allow-unsupported) would keep such apps building.Found while compiling a Rails API app with
--target spinel.