Rendering with layouts
I may be doing something wrong, but I'm trying to add a layout so I can standardize some metadata in the JSON output.
I've got an layouts\api.jb file and I've requested that layout in the controller generating the json output.
ArgumentError in Api::PostsController#show
unknown keywords: id, title, slug, blurb, classification, higher_ed, sponsor_label, comment_count, share_count, tags, authors, image, date, content, description, schema, meta, chartbeat
Extracted source (around line #172):
def initialize(*)
@html_safe = true
super
end
def initialize_copy(other)
....
.bundle/gems/activesupport-4.2.7.1/lib/active_support/core_ext/string/output_safety.rb:172:in `initialize'
.bundle/gems/activesupport-4.2.7.1/lib/active_support/core_ext/string/output_safety.rb:172:in `initialize'
.bundle/gems/actionview-4.2.7.1/lib/action_view/flows.rb:18:in `new'
.bundle/gems/actionview-4.2.7.1/lib/action_view/flows.rb:18:in `set'
.bundle/gems/actionview-4.2.7.1/lib/action_view/renderer/template_renderer.rb:65:in `render_with_layout'
.bundle/gems/skylight-0.10.6/lib/skylight/probes/action_view.rb:32:in `block in render_with_layout'
.bundle/gems/actionview-4.2.7.1/lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument'
.bundle/gems/activesupport-4.2.7.1/lib/active_support/notifications.rb:164:in `block in instrument'
.bundle/gems/activesupport-4.2.7.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
.bundle/gems/activesupport-4.2.7.1/lib/active_support/notifications.rb:164:in `instrument'
.bundle/gems/actionview-4.2.7.1/lib/action_view/renderer/abstract_renderer.rb:39:in `instrument'
.bundle/gems/skylight-0.10.6/lib/skylight/probes/action_view.rb:31:in `render_with_layout'
.bundle/gems/actionview-4.2.7.1/lib/action_view/renderer/template_renderer.rb:52:in `render_template'
I've tried ERB layout template, using content_for, assigning the template output to variables (including instance vars) and using yield or ERB rendering. All lead to similar issues.
Am I totally missing something simple @amatsuda ?
Sadly, #10 only works for legacy Rails applications (v5 and prior).
For anyone wondering, my current workaround for an SPA is to define a layout helper and use this in all views:
app/helpers/layout_helper.rb
module LayoutHelper
def layout(**meta)
meta[:notices] = @notices if @notices.any? # show flash messages
meta[:redirect] = @redirect if @redirect.present? # trigger frontend routing
{ meta:, data: yield }
end
end
app/views/users/show.json.jb
layout do
current_user.attributes.slice("id", "name", "email") if user_signed_in?
end
notes on the protocol
-
API responses always have this shape:
interface APIResponse<T = any> { meta: { notices?: string[] redirect?: string } data: T } -
the API client first extracts and processes the
metaproperty (by passing it into various stores) -
the API client then extracts and returns the
dataproperty to the caller
I've tried to update #10 to get to work with at least the current Rails version (7.2), but wasn't able to yet.