jbuilder 2.13.0 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23152c62d2a748a3a3b190dba588de44dbb8577aff5ad930fa6aa7e29e935e50
4
- data.tar.gz: 1a79f24f284ede18d9aea34702fe7bff5f70064c8dd6d8a372e8bd9ec4f5d266
3
+ metadata.gz: c3f0a36b10c8ab54a2378daf5acb8f59126b9fe97dcebddac33bd2a4bd63b846
4
+ data.tar.gz: 0062fc739c0c288fb9f1864db1189b05bd0d0c6943481dc56bf00eb9a33f2662
5
5
  SHA512:
6
- metadata.gz: 0fb3a664bd96a0263ed6a155b385a634efcb26e157a1e8d7592da3f3baa1a4ed6d717bead553169d1fd6e540a35f1847925195e07ede281e6d845e6f649cd537
7
- data.tar.gz: c9d1fd1cc89b68ffea4b5b6090ae2ed1de25e75442923a2dc9b16fda0bdfbdb7470d8ada71657d06ad8db1c64c41acacf1e1235891c794c146b3e16758978cff
6
+ metadata.gz: 77d5b7b40bf5445c727b4e3fa4ddce979bd6d04c9a21336b1a486d6884d1f8cede1b0473944053ae5f1e2fc593cf1464e9e7c78b82fc230ef12381e25be53360
7
+ data.tar.gz: 4dd011c5f03e7e7f44cf456241078a218c420c9f80951480c2102a39fbcfb2ecc2ea2fd0a170025151e79c8db83517261c9cb53cd085b65faa8a7d6bbae3a922
@@ -0,0 +1,9 @@
1
+ {
2
+ "features": {
3
+ "ghcr.io/devcontainers/features/github-cli:1": {
4
+ "version": "1.1.0",
5
+ "resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671",
6
+ "integrity": "sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671"
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,25 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/ruby
3
+ {
4
+ "name": "jbuilder",
5
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6
+ "image": "ghcr.io/rails/devcontainer/images/ruby:4.0.4",
7
+ "features": {
8
+ "ghcr.io/devcontainers/features/github-cli:1": {}
9
+ }
10
+
11
+ // Features to add to the dev container. More info: https://containers.dev/features.
12
+ // "features": {},
13
+
14
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
15
+ // "forwardPorts": [],
16
+
17
+ // Use 'postCreateCommand' to run commands after the container is created.
18
+ // "postCreateCommand": "ruby --version",
19
+
20
+ // Configure tool-specific properties.
21
+ // "customizations": {},
22
+
23
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
24
+ // "remoteUser": "root"
25
+ }
@@ -5,7 +5,7 @@ on: [push, pull_request]
5
5
  jobs:
6
6
  test:
7
7
  name: Ruby ${{ matrix.ruby }} (${{ matrix.gemfile }})
8
- runs-on: ubuntu-20.04
8
+ runs-on: ubuntu-latest
9
9
  continue-on-error: ${{ matrix.gemfile == 'rails_head' }}
10
10
  env:
11
11
  BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
@@ -19,26 +19,43 @@ jobs:
19
19
  - "3.1"
20
20
  - "3.2"
21
21
  - "3.3"
22
+ - "3.4"
23
+ - "4.0"
22
24
 
23
25
  gemfile:
24
26
  - "rails_7_0"
25
27
  - "rails_7_1"
28
+ - "rails_7_2"
29
+ - "rails_8_0"
30
+ - "rails_8_1"
26
31
  - "rails_head"
27
32
 
28
33
  exclude:
34
+ - ruby: '3.0'
35
+ gemfile: rails_7_2
36
+ - ruby: '3.0'
37
+ gemfile: rails_8_0
38
+ - ruby: '3.0'
39
+ gemfile: rails_8_1
29
40
  - ruby: '3.0'
30
41
  gemfile: rails_head
31
-
32
- include:
42
+ - ruby: '3.1'
43
+ gemfile: rails_7_2
44
+ - ruby: '3.1'
45
+ gemfile: rails_8_0
46
+ - ruby: '3.1'
47
+ gemfile: rails_8_1
33
48
  - ruby: '3.1'
34
49
  gemfile: rails_head
35
50
  - ruby: '3.2'
36
51
  gemfile: rails_head
37
- - ruby: head
38
- gemfile: rails_head
52
+ - ruby: '3.4'
53
+ gemfile: rails_7_0
54
+ - ruby: '4.0'
55
+ gemfile: rails_7_0
39
56
 
40
57
  steps:
41
- - uses: actions/checkout@v4
58
+ - uses: actions/checkout@v6
42
59
 
43
60
  - uses: ruby/setup-ruby@v1
44
61
  with:
data/Appraisals CHANGED
@@ -1,13 +1,26 @@
1
- if RUBY_VERSION >= "2.7.0"
2
- appraise "rails-7-0" do
3
- gem "rails", "~> 7.0.0"
4
- end
5
-
6
- appraise "rails-7-1" do
7
- gem "rails", "~> 7.1.0"
8
- end
9
-
10
- appraise "rails-head" do
11
- gem "rails", github: "rails/rails", branch: "main"
12
- end
1
+ # frozen_string_literal: true
2
+
3
+ appraise "rails-7-0" do
4
+ gem "rails", "~> 7.0.0"
5
+ gem "concurrent-ruby", "< 1.3.5" # to avoid problem described in https://github.com/rails/rails/pull/54264
6
+ end
7
+
8
+ appraise "rails-7-1" do
9
+ gem "rails", "~> 7.1.0"
10
+ end
11
+
12
+ appraise "rails-7-2" do
13
+ gem "rails", "~> 7.2.0"
14
+ end
15
+
16
+ appraise "rails-8-0" do
17
+ gem "rails", "~> 8.0.0"
18
+ end
19
+
20
+ appraise "rails-8-1" do
21
+ gem "rails", "~> 8.1.0"
22
+ end
23
+
24
+ appraise "rails-head" do
25
+ gem "rails", github: "rails/rails", branch: "main"
13
26
  end
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  gemspec
data/README.md CHANGED
@@ -5,7 +5,7 @@ manipulating giant hash structures. This is particularly helpful when the
5
5
  generation process is fraught with conditionals and loops. Here's a simple
6
6
  example:
7
7
 
8
- ``` ruby
8
+ ```ruby
9
9
  # app/views/messages/show.json.jbuilder
10
10
 
11
11
  json.content format_content(@message.content)
@@ -31,7 +31,7 @@ end
31
31
 
32
32
  This will build the following structure:
33
33
 
34
- ``` javascript
34
+ ```javascript
35
35
  {
36
36
  "content": "<p>This is <i>serious</i> monkey business</p>",
37
37
  "created_at": "2011-10-29T20:45:28-05:00",
@@ -57,9 +57,11 @@ This will build the following structure:
57
57
  }
58
58
  ```
59
59
 
60
+ ## Dynamically Defined Attributes
61
+
60
62
  To define attribute and structure names dynamically, use the `set!` method:
61
63
 
62
- ``` ruby
64
+ ```ruby
63
65
  json.set! :author do
64
66
  json.set! :name, 'David'
65
67
  end
@@ -67,10 +69,11 @@ end
67
69
  # => {"author": { "name": "David" }}
68
70
  ```
69
71
 
72
+ ## Merging Existing Hash or Array
70
73
 
71
74
  To merge existing hash or array to current context:
72
75
 
73
- ``` ruby
76
+ ```ruby
74
77
  hash = { author: { name: "David" } }
75
78
  json.post do
76
79
  json.title "Merge HOWTO"
@@ -80,9 +83,11 @@ end
80
83
  # => "post": { "title": "Merge HOWTO", "author": { "name": "David" } }
81
84
  ```
82
85
 
83
- Top level arrays can be handled directly. Useful for index and other collection actions.
86
+ ## Top Level Arrays
87
+
88
+ Top level arrays can be handled directly. Useful for index and other collection actions.
84
89
 
85
- ``` ruby
90
+ ```ruby
86
91
  # @comments = @post.comments
87
92
 
88
93
  json.array! @comments do |comment|
@@ -95,12 +100,14 @@ json.array! @comments do |comment|
95
100
  end
96
101
  end
97
102
 
98
- # => [ { "body": "great post...", "author": { "first_name": "Joe", "last_name": "Bloe" }} ]
103
+ # => [ { "body": "great post...", "author": { "first_name": "Joe", "last_name": "Blow" }} ]
99
104
  ```
100
105
 
106
+ ## Array Attributes
107
+
101
108
  You can also extract attributes from array directly.
102
109
 
103
- ``` ruby
110
+ ```ruby
104
111
  # @people = People.all
105
112
 
106
113
  json.array! @people, :id, :name
@@ -108,6 +115,8 @@ json.array! @people, :id, :name
108
115
  # => [ { "id": 1, "name": "David" }, { "id": 2, "name": "Jamie" } ]
109
116
  ```
110
117
 
118
+ ## Plain Arrays
119
+
111
120
  To make a plain array without keys, construct and pass in a standard Ruby array.
112
121
 
113
122
  ```ruby
@@ -118,6 +127,8 @@ json.people my_array
118
127
  # => "people": [ "David", "Jamie" ]
119
128
  ```
120
129
 
130
+ ## Child Objects
131
+
121
132
  You don't always have or need a collection when building an array.
122
133
 
123
134
  ```ruby
@@ -135,9 +146,11 @@ end
135
146
  # => { "people": [ { "id": 1, "name": "David" }, { "id": 2, "name": "Jamie" } ] }
136
147
  ```
137
148
 
138
- Jbuilder objects can be directly nested inside each other. Useful for composing objects.
149
+ ## Nested Jbuilder Objects
150
+
151
+ Jbuilder objects can be directly nested inside each other. Useful for composing objects.
139
152
 
140
- ``` ruby
153
+ ```ruby
141
154
  class Person
142
155
  # ... Class Definition ... #
143
156
  def to_builder
@@ -163,11 +176,13 @@ company.to_builder.target!
163
176
  # => {"name":"Doodle Corp","president":{"name":"John Stobs","age":58}}
164
177
  ```
165
178
 
179
+ ## Rails Integration
180
+
166
181
  You can either use Jbuilder stand-alone or directly as an ActionView template
167
182
  language. When required in Rails, you can create views à la show.json.jbuilder
168
183
  (the json is already yielded):
169
184
 
170
- ``` ruby
185
+ ```ruby
171
186
  # Any helpers available to views are available to the builder
172
187
  json.content format_content(@message.content)
173
188
  json.(@message, :created_at, :updated_at)
@@ -183,6 +198,8 @@ if current_user.admin?
183
198
  end
184
199
  ```
185
200
 
201
+ ## Partials
202
+
186
203
  You can use partials as well. The following will render the file
187
204
  `views/comments/_comments.json.jbuilder`, and set a local variable
188
205
  `comments` with all this message's comments, which you can use inside
@@ -192,6 +209,13 @@ the partial.
192
209
  json.partial! 'comments/comments', comments: @message.comments
193
210
  ```
194
211
 
212
+ You can also render an object to a partial inline under a key.
213
+
214
+ ```ruby
215
+ json.post @post, partial: 'posts/post', as: :post
216
+ # => { "post": { "title": "Hello World!", "author": { "name": "David" } } }
217
+ ```
218
+
195
219
  It's also possible to render collections of partials:
196
220
 
197
221
  ```ruby
@@ -202,9 +226,24 @@ json.partial! 'posts/post', collection: @posts, as: :post
202
226
 
203
227
  # or
204
228
  json.partial! partial: 'posts/post', collection: @posts, as: :post
229
+ ```
205
230
 
206
- # or
231
+ You can also render to a collection of partials inline under a key.
232
+
233
+ ```ruby
207
234
  json.comments @post.comments, partial: 'comments/comment', as: :comment
235
+ # => { "comments": [{ "content": "Hello everyone!" }, { "content": "To you my good sir!" }] }
236
+ ```
237
+
238
+ You can also provide other locals to the partial you're rendering to.
239
+
240
+ ```ruby
241
+ # Provide the `include_body` local to the partial when rendering a single object
242
+ json.post @post, partial: 'posts/post', as: :post, include_body: true
243
+
244
+ # Provide a local to the partial when rendering a collection.
245
+ # Each item in the collection will render with `include_author: true`.
246
+ json.comments @post.comments, partial: 'comments/comment', as: :comment, include_author: true
208
247
  ```
209
248
 
210
249
  The `as: :some_symbol` is used with partials. It will take care of mapping the passed in object to a variable for the
@@ -215,15 +254,15 @@ then the object is passed to the partial as the variable `some_symbol`.
215
254
  Be sure not to confuse the `as:` option to mean nesting of the partial. For example:
216
255
 
217
256
  ```ruby
218
- # Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
219
- # Note, `comment` attributes are "inlined".
220
- json.partial! @comment, as: :comment
257
+ # Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
258
+ # Note, `comment` attributes are "inlined".
259
+ json.partial! @comment, as: :comment
221
260
  ```
222
261
 
223
262
  is quite different from:
224
263
 
225
264
  ```ruby
226
- # comment attributes are nested under a "comment" property
265
+ # comment attributes are nested under a "comment" property
227
266
  json.comment do
228
267
  json.partial! "/comments/comment.json.jbuilder", comment: @comment
229
268
  end
@@ -239,10 +278,11 @@ json.partial! 'sub_template', locals: { user: user }
239
278
  json.partial! 'sub_template', user: user
240
279
  ```
241
280
 
281
+ ## Null Values
242
282
 
243
283
  You can explicitly make Jbuilder object return null if you want:
244
284
 
245
- ``` ruby
285
+ ```ruby
246
286
  json.extract! @post, :id, :title, :content, :published_at
247
287
  json.author do
248
288
  if @post.anonymous?
@@ -303,9 +343,9 @@ This will include both records as part of the cache key and updating either of t
303
343
  ## Formatting Keys
304
344
 
305
345
  Keys can be auto formatted using `key_format!`, this can be used to convert
306
- keynames from the standard ruby_format to camelCase:
346
+ key names from the standard ruby_format to camelCase:
307
347
 
308
- ``` ruby
348
+ ```ruby
309
349
  json.key_format! camelize: :lower
310
350
  json.first_name 'David'
311
351
 
@@ -315,7 +355,7 @@ json.first_name 'David'
315
355
  You can set this globally with the class method `key_format` (from inside your
316
356
  environment.rb for example):
317
357
 
318
- ``` ruby
358
+ ```ruby
319
359
  Jbuilder.key_format camelize: :lower
320
360
  ```
321
361
 
@@ -323,7 +363,7 @@ By default, key format is not applied to keys of hashes that are
323
363
  passed to methods like `set!`, `array!` or `merge!`. You can opt into
324
364
  deeply transforming these as well:
325
365
 
326
- ``` ruby
366
+ ```ruby
327
367
  json.key_format! camelize: :lower
328
368
  json.deep_format_keys!
329
369
  json.settings([{some_value: "abc"}])
@@ -334,7 +374,7 @@ json.settings([{some_value: "abc"}])
334
374
  You can set this globally with the class method `deep_format_keys` (from inside your
335
375
  environment.rb for example):
336
376
 
337
- ``` ruby
377
+ ```ruby
338
378
  Jbuilder.deep_format_keys true
339
379
  ```
340
380
 
@@ -350,4 +390,5 @@ features and discuss issues.
350
390
  See [CONTRIBUTING](CONTRIBUTING.md).
351
391
 
352
392
  ## License
393
+
353
394
  Jbuilder is released under the [MIT License](http://www.opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/setup"
2
4
  require "bundler/gem_tasks"
3
5
  require "rake/testtask"
data/bin/test CHANGED
@@ -1,4 +1,4 @@
1
- #!/bin/env bash
1
+ #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
4
  bundle install
@@ -6,5 +6,6 @@ gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
8
  gem "rails", "~> 7.0.0"
9
+ gem "concurrent-ruby", "< 1.3.5"
9
10
 
10
11
  gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
8
+ gem "rails", "~> 7.2.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
8
+ gem "rails", "~> 8.0.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
8
+ gem "rails", "~> 8.1.0"
9
+
10
+ gemspec path: "../"
data/jbuilder.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "lib/jbuilder/version"
2
4
 
3
5
  Gem::Specification.new do |s|
@@ -9,10 +11,10 @@ Gem::Specification.new do |s|
9
11
  s.homepage = 'https://github.com/rails/jbuilder'
10
12
  s.license = 'MIT'
11
13
 
12
- s.required_ruby_version = '>= 2.2.2'
14
+ s.required_ruby_version = '>= 3.0.0'
13
15
 
14
- s.add_dependency 'activesupport', '>= 5.0.0'
15
- s.add_dependency 'actionview', '>= 5.0.0'
16
+ s.add_dependency 'activesupport', '>= 7.0.0'
17
+ s.add_dependency 'actionview', '>= 7.0.0'
16
18
 
17
19
  if RUBY_ENGINE == 'rbx'
18
20
  s.add_development_dependency('racc')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators/named_base'
2
4
  require 'rails/generators/resource_helpers'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators'
2
4
  require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
3
5
 
@@ -13,6 +15,10 @@ module Rails
13
15
  def permitted_params
14
16
  attributes_names.map { |name| ":#{name}" }.join(', ')
15
17
  end unless private_method_defined? :permitted_params
18
+
19
+ def status_unprocessable_content
20
+ ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422) rescue :unprocessable_content
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -25,7 +25,7 @@ class <%= controller_class_name %>Controller < ApplicationController
25
25
  if @<%= orm_instance.save %>
26
26
  render :show, status: :created, location: <%= "@#{singular_table_name}" %>
27
27
  else
28
- render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
28
+ render json: <%= "@#{orm_instance.errors}" %>, status: :<%= status_unprocessable_content.to_s %>
29
29
  end
30
30
  end
31
31
 
@@ -35,7 +35,7 @@ class <%= controller_class_name %>Controller < ApplicationController
35
35
  if @<%= orm_instance.update("#{singular_table_name}_params") %>
36
36
  render :show, status: :ok, location: <%= "@#{singular_table_name}" %>
37
37
  else
38
- render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity
38
+ render json: <%= "@#{orm_instance.errors}" %>, status: :<%= status_unprocessable_content.to_s %>
39
39
  end
40
40
  end
41
41
 
@@ -33,8 +33,8 @@ class <%= controller_class_name %>Controller < ApplicationController
33
33
  format.html { redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully created.") %> }
34
34
  format.json { render :show, status: :created, location: <%= "@#{singular_table_name}" %> }
35
35
  else
36
- format.html { render :new, status: :unprocessable_entity }
37
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
36
+ format.html { render :new, status: :<%= status_unprocessable_content.to_s %> }
37
+ format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :<%= status_unprocessable_content.to_s %> }
38
38
  end
39
39
  end
40
40
  end
@@ -43,11 +43,11 @@ class <%= controller_class_name %>Controller < ApplicationController
43
43
  def update
44
44
  respond_to do |format|
45
45
  if @<%= orm_instance.update("#{singular_table_name}_params") %>
46
- format.html { redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully updated.") %> }
46
+ format.html { redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully updated.") %>, status: :see_other }
47
47
  format.json { render :show, status: :ok, location: <%= "@#{singular_table_name}" %> }
48
48
  else
49
- format.html { render :edit, status: :unprocessable_entity }
50
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
49
+ format.html { render :edit, status: :<%= status_unprocessable_content.to_s %> }
50
+ format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :<%= status_unprocessable_content.to_s %> }
51
51
  end
52
52
  end
53
53
  end
@@ -57,7 +57,7 @@ class <%= controller_class_name %>Controller < ApplicationController
57
57
  @<%= orm_instance.destroy %>
58
58
 
59
59
  respond_to do |format|
60
- format.html { redirect_to <%= index_helper %>_path, status: :see_other, notice: <%= %("#{human_name} was successfully destroyed.") %> }
60
+ format.html { redirect_to <%= index_helper %>_path, notice: <%= %("#{human_name} was successfully destroyed.") %>, status: :see_other }
61
61
  format.json { head :no_content }
62
62
  end
63
63
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Jbuilder
2
4
  class Blank
3
5
  def ==(other)