Skip to content

Support integrating with Action View layouts - #623

Open
seanpdoyle wants to merge 1 commit into
rails:mainfrom
seanpdoyle:action-view-layout
Open

seanpdoyle wants to merge 1 commit into
rails:mainfrom
seanpdoyle:action-view-layout

Conversation

@seanpdoyle

@seanpdoyle seanpdoyle commented Sep 4, 2026 •

Copy link
Copy Markdown

Related to #250
Related to #172

Add support for Rails' built-in layout templates defined in app/views/layouts/. Layouts can be used to extract properties or structures that are shared across responses.

For example, a PostsController that inherits from ApplicationController will render its templates declared in app/views/posts/ into the layout declared in
app/views/layouts/application.json.jbuilder:

# app/views/layouts/application.json.jbuilder
json.merge! yield
json.servedAt Time.current

# app/views/posts/index.json.jbuilder
json.partial! 'posts/post', collection: @posts, as: :post

Related to rails#250
Related to rails#172

Add support for Rails' built-in layout templates defined in
`app/views/layouts/`. Layouts can be used to extract properties or
structures that are shared across responses.

For example, a `PostsController` that inherits from
`ApplicationController` will render its templates declared in
`app/views/posts/` *into* the layout declared in
`app/views/layouts/application.json.jbuilder`:

    # app/views/layouts/application.json.jbuilder
    json.merge! yield
    json.servedAt Time.current

    # app/views/posts/index.json.jbuilder
    json.partial! 'posts/post', collection: @posts, as: :post
@malomalo

malomalo commented Sep 4, 2026

Copy link
Copy Markdown

@seanpdoyle I maintain TurboStreamer it might be a better fit for you. It's a Jbuilder-ish DSL over streaming encoders (Oj/Yajl), and supports layouts and improved caching performance.

A layout calls json.yield! wherever the template's JSON belongs:

# app/views/layouts/application.json.streamer
json.object! do
  json.meta do
    json.object! { json.version 1 }
  end
  json.key! :data
  json.yield!
end

# app/views/posts/index.json.streamer
json.array! @posts, :id, :title

# => { "meta": { "version": 1 }, "data": [ { "id": 1, "title": "..." } ] }

The layout and the template share one builder, so the template writes straight into the same stream at the point it's yielded — nothing is encoded to a string and re-parsed, which also means the template's JSON can land at a key or inside an array rather than only merging into the root. This also enables streaming support.

More in the README. Happy to answer questions if you give it a look.

@seanpdoyle

Copy link
Copy Markdown
Author

@malomalo That seems like a compelling project, thanks for the recommendation!

I'm sure that there's plenty of innovation out there worth trying. The motivation behind this PR is less about innovating, and more about bringing jbuilder more in line with existing Action View and Rails conventions. Since jbuilder is part of most rails new-generated Gemfiles, I think many would benefit from any improvements.

supports layouts and improved caching performance.

That's exciting! Are there any opportunities to upstream performance improvements back into jbuilder?

@malomalo

malomalo commented Sep 5, 2026 •

Copy link
Copy Markdown

That's exciting! Are there any opportunities to upstream performance improvements back into jbuilder?

@seanpdoyle I tried for a while with my fork to get jBuilder off hashes at least partially but if i recall correctly it's impossible due to syntax and needing to know how to insert the string. I forget the concrete example convinced me it wasn't possible.

I just remember your coworkers did something similar recently they might have and idea.

*redacting/editing comment - I jumped to conclusions with a few things in the earlier comment and props-template although similar on first look approaches some things differently

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants