Repository navigation
Object-REST Mapper, revisited against the REST constraints - #32
Merged
Merged
Conversation
Object-REST Mapper, revisited against the REST constraints.
Uniform interface: Funicular::Schema derives a model's endpoint table
from the Rails routes to its controller (`resources :posts` gives
posts#index as "all", posts#show as "find"; other actions keep their
names). Escape hatches: controller:, endpoints: (a "controller#action"
alias, a hand-written entry, or nil to hide one), routes: false, and a
nil model_class. On the client, path placeholders fill from the call
(Comment.all(post_id: 3) -> /posts/3/comments) or the record's
attributes; one unfilled segment takes the id whatever the route calls
it. A missing endpoint or segment raises instead of a silent no-op.
Self-descriptive messages: a 422 with { errors: record.errors } lands
on the record's errors and is yielded as a Funicular::Model::Errors,
like a client-side validation failure.
Cache: a replica model remembers each GET's ETag in the replica
database and sends If-None-Match; a 304 is answered from the replica
rows the last response listed, with no write and no change event.
Replica rows now merge per attribute so summary and detail
representations build one row. Model.absorb seeds the replica from
SSR state.
Version 0.6.0.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018W7QSXsvaDqYZvjG3pptyf
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018W7QSXsvaDqYZvjG3pptyf
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018W7QSXsvaDqYZvjG3pptyf
The record id filled any single empty placeholder, so a comment without post_id sent its own id as the parent (/posts/7/comments/7). Only the last placeholder takes the id now; an empty parent raises ArgumentError. update assigned the pending attributes before it built the path, so update(slug: "new") requested /pages/new. The setter keeps the value from before the first pending change, and __path_source uses it. Move the 0.6.0 entries out of the dated 0.5.2 section of the CHANGELOG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VaokYGa9iWeyJSe6w3EeS
- Schema.build accepts an explicit endpoints: {} for a model with no
REST side; it raises only when endpoints: is omitted and no route
matches.
- Route derivation drops optional groups such as (/:locale) and skips
glob routes, so no literal "(" or "*" reaches a client path.
- find sends the params the path does not take as the query string,
like all. destroy raises ArgumentError on such a keyword, because a
DELETE carries no query.
- The ETag cache key includes the table, so two models that GET one
path no longer share an entry.
- A 304 reads its rows with one IN query instead of one per id.
- create no longer writes server errors onto an unreachable candidate.
- Document that the server must send a cleared attribute as null, and
rewrite passive sentences in the conditional GET docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VaokYGa9iWeyJSe6w3EeS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uniform interface: Funicular::Schema derives a model's endpoint table
from the Rails routes to its controller (
resources :postsgivesposts#index as "all", posts#show as "find"; other actions keep their
names). Escape hatches: controller:, endpoints: (a "controller#action"
alias, a hand-written entry, or nil to hide one), routes: false, and a
nil model_class. On the client, path placeholders fill from the call
(Comment.all(post_id: 3) -> /posts/3/comments) or the record's
attributes; one unfilled segment takes the id whatever the route calls
it. A missing endpoint or segment raises instead of a silent no-op.
Self-descriptive messages: a 422 with { errors: record.errors } lands
on the record's errors and is yielded as a Funicular::Model::Errors,
like a client-side validation failure.
Cache: a replica model remembers each GET's ETag in the replica
database and sends If-None-Match; a 304 is answered from the replica
rows the last response listed, with no write and no change event.
Replica rows now merge per attribute so summary and detail
representations build one row. Model.absorb seeds the replica from
SSR state.
Version 0.6.0.