amatsuda / jb

A simple and fast JSON API template engine for Ruby on Rails
MIT License
1.29k stars 43 forks source link

Rendering with layouts #7

Open johnpaulashenfelter opened 8 years ago

johnpaulashenfelter commented 8 years ago

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 ?

dmke commented 1 month ago

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 ```ruby 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 ```ruby layout do current_user.attributes.slice("id", "name", "email") if user_signed_in? end ```
notes on the protocol - API responses always have this shape: ```ts interface APIResponse { meta: { notices?: string[] redirect?: string } data: T } ``` - the API client first extracts and processes the `meta` property (by passing it into various stores) - the API client then extracts and returns the `data` property 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.