jbuilder 2.13.0 → 2.14.0
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 +4 -4
- data/.devcontainer/devcontainer.json +25 -0
- data/.github/workflows/ruby.yml +14 -7
- data/Appraisals +21 -12
- data/Gemfile +2 -0
- data/README.md +38 -19
- data/Rakefile +2 -0
- data/bin/test +1 -1
- data/gemfiles/rails_7_0.gemfile +1 -0
- data/gemfiles/rails_7_2.gemfile +10 -0
- data/gemfiles/rails_8_0.gemfile +10 -0
- data/jbuilder.gemspec +5 -3
- data/lib/generators/rails/jbuilder_generator.rb +2 -0
- data/lib/generators/rails/scaffold_controller_generator.rb +2 -0
- data/lib/generators/rails/templates/controller.rb +2 -2
- data/lib/jbuilder/blank.rb +2 -0
- data/lib/jbuilder/collection_renderer.rb +19 -77
- data/lib/jbuilder/errors.rb +3 -1
- data/lib/jbuilder/jbuilder.rb +3 -1
- data/lib/jbuilder/jbuilder_dependency_tracker.rb +2 -0
- data/lib/jbuilder/jbuilder_template.rb +29 -52
- data/lib/jbuilder/key_formatter.rb +19 -21
- data/lib/jbuilder/railtie.rb +15 -17
- data/lib/jbuilder/version.rb +4 -2
- data/lib/jbuilder.rb +38 -33
- data/test/jbuilder_generator_test.rb +6 -8
- data/test/jbuilder_template_test.rb +82 -78
- data/test/jbuilder_test.rb +7 -9
- data/test/scaffold_api_controller_generator_test.rb +52 -60
- data/test/scaffold_controller_generator_test.rb +25 -31
- data/test/test_helper.rb +1 -1
- metadata +13 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea5bb97ea25a962edc387aeeffaeb9dd66622da566f7225543a1492e77328cd9
|
4
|
+
data.tar.gz: ad752c5b04270cf297e1e0e0fe41223d886a1042bde3443a37b25215c51347cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01dab8d566ba11a9f8baed7972ad962ef4e6090807ff920889e5f4bd64bb69f7d81fe372b3bb243f420222a7742813cd27dd19ba5b213ecd6773a3ff93307a7e
|
7
|
+
data.tar.gz: bbf81f248f73b27d20d16de9a313327f7d82024c2304177cad74ff000942be69c1f43435c9e9cc6126499119e36d4c327750489e9e8f6add0658eb8928d16780
|
@@ -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:3.4.5",
|
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
|
+
}
|
data/.github/workflows/ruby.yml
CHANGED
@@ -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-
|
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,23 +19,30 @@ jobs:
|
|
19
19
|
- "3.1"
|
20
20
|
- "3.2"
|
21
21
|
- "3.3"
|
22
|
+
- "3.4"
|
22
23
|
|
23
24
|
gemfile:
|
24
25
|
- "rails_7_0"
|
25
26
|
- "rails_7_1"
|
27
|
+
- "rails_7_2"
|
28
|
+
- "rails_8_0"
|
26
29
|
- "rails_head"
|
27
30
|
|
28
31
|
exclude:
|
32
|
+
- ruby: '3.0'
|
33
|
+
gemfile: rails_7_2
|
34
|
+
- ruby: '3.0'
|
35
|
+
gemfile: rails_8_0
|
29
36
|
- ruby: '3.0'
|
30
37
|
gemfile: rails_head
|
31
|
-
|
32
|
-
|
38
|
+
- ruby: '3.1'
|
39
|
+
gemfile: rails_7_2
|
40
|
+
- ruby: '3.1'
|
41
|
+
gemfile: rails_8_0
|
33
42
|
- ruby: '3.1'
|
34
43
|
gemfile: rails_head
|
35
|
-
- ruby: '3.
|
36
|
-
gemfile:
|
37
|
-
- ruby: head
|
38
|
-
gemfile: rails_head
|
44
|
+
- ruby: '3.4'
|
45
|
+
gemfile: rails_7_0
|
39
46
|
|
40
47
|
steps:
|
41
48
|
- uses: actions/checkout@v4
|
data/Appraisals
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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-head" do
|
21
|
+
gem "rails", github: "rails/rails", branch: "main"
|
13
22
|
end
|
data/Gemfile
CHANGED
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
|
-
```
|
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
|
-
```
|
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
|
-
```
|
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
|
-
```
|
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
|
86
|
+
## Top Level Arrays
|
87
|
+
|
88
|
+
Top level arrays can be handled directly. Useful for index and other collection actions.
|
84
89
|
|
85
|
-
```
|
90
|
+
```ruby
|
86
91
|
# @comments = @post.comments
|
87
92
|
|
88
93
|
json.array! @comments do |comment|
|
@@ -98,9 +103,11 @@ end
|
|
98
103
|
# => [ { "body": "great post...", "author": { "first_name": "Joe", "last_name": "Bloe" }} ]
|
99
104
|
```
|
100
105
|
|
106
|
+
## Array Attributes
|
107
|
+
|
101
108
|
You can also extract attributes from array directly.
|
102
109
|
|
103
|
-
```
|
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
|
-
|
149
|
+
## Nested Jbuilder Objects
|
150
|
+
|
151
|
+
Jbuilder objects can be directly nested inside each other. Useful for composing objects.
|
139
152
|
|
140
|
-
```
|
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
|
-
```
|
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
|
@@ -215,15 +232,15 @@ then the object is passed to the partial as the variable `some_symbol`.
|
|
215
232
|
Be sure not to confuse the `as:` option to mean nesting of the partial. For example:
|
216
233
|
|
217
234
|
```ruby
|
218
|
-
|
219
|
-
|
220
|
-
|
235
|
+
# Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
|
236
|
+
# Note, `comment` attributes are "inlined".
|
237
|
+
json.partial! @comment, as: :comment
|
221
238
|
```
|
222
239
|
|
223
240
|
is quite different from:
|
224
241
|
|
225
242
|
```ruby
|
226
|
-
|
243
|
+
# comment attributes are nested under a "comment" property
|
227
244
|
json.comment do
|
228
245
|
json.partial! "/comments/comment.json.jbuilder", comment: @comment
|
229
246
|
end
|
@@ -239,10 +256,11 @@ json.partial! 'sub_template', locals: { user: user }
|
|
239
256
|
json.partial! 'sub_template', user: user
|
240
257
|
```
|
241
258
|
|
259
|
+
## Null Values
|
242
260
|
|
243
261
|
You can explicitly make Jbuilder object return null if you want:
|
244
262
|
|
245
|
-
```
|
263
|
+
```ruby
|
246
264
|
json.extract! @post, :id, :title, :content, :published_at
|
247
265
|
json.author do
|
248
266
|
if @post.anonymous?
|
@@ -305,7 +323,7 @@ This will include both records as part of the cache key and updating either of t
|
|
305
323
|
Keys can be auto formatted using `key_format!`, this can be used to convert
|
306
324
|
keynames from the standard ruby_format to camelCase:
|
307
325
|
|
308
|
-
```
|
326
|
+
```ruby
|
309
327
|
json.key_format! camelize: :lower
|
310
328
|
json.first_name 'David'
|
311
329
|
|
@@ -315,7 +333,7 @@ json.first_name 'David'
|
|
315
333
|
You can set this globally with the class method `key_format` (from inside your
|
316
334
|
environment.rb for example):
|
317
335
|
|
318
|
-
```
|
336
|
+
```ruby
|
319
337
|
Jbuilder.key_format camelize: :lower
|
320
338
|
```
|
321
339
|
|
@@ -323,7 +341,7 @@ By default, key format is not applied to keys of hashes that are
|
|
323
341
|
passed to methods like `set!`, `array!` or `merge!`. You can opt into
|
324
342
|
deeply transforming these as well:
|
325
343
|
|
326
|
-
```
|
344
|
+
```ruby
|
327
345
|
json.key_format! camelize: :lower
|
328
346
|
json.deep_format_keys!
|
329
347
|
json.settings([{some_value: "abc"}])
|
@@ -334,7 +352,7 @@ json.settings([{some_value: "abc"}])
|
|
334
352
|
You can set this globally with the class method `deep_format_keys` (from inside your
|
335
353
|
environment.rb for example):
|
336
354
|
|
337
|
-
```
|
355
|
+
```ruby
|
338
356
|
Jbuilder.deep_format_keys true
|
339
357
|
```
|
340
358
|
|
@@ -350,4 +368,5 @@ features and discuss issues.
|
|
350
368
|
See [CONTRIBUTING](CONTRIBUTING.md).
|
351
369
|
|
352
370
|
## License
|
371
|
+
|
353
372
|
Jbuilder is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
data/bin/test
CHANGED
data/gemfiles/rails_7_0.gemfile
CHANGED
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 = '>=
|
14
|
+
s.required_ruby_version = '>= 3.0.0'
|
13
15
|
|
14
|
-
s.add_dependency 'activesupport', '>=
|
15
|
-
s.add_dependency 'actionview', '>=
|
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')
|
@@ -43,7 +43,7 @@ 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
49
|
format.html { render :edit, status: :unprocessable_entity }
|
@@ -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,
|
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
|
data/lib/jbuilder/blank.rb
CHANGED
@@ -1,37 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'delegate'
|
2
|
-
require 'active_support/concern'
|
3
4
|
require 'action_view'
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'action_view/renderer/collection_renderer'
|
7
|
-
rescue LoadError
|
8
|
-
require 'action_view/renderer/partial_renderer'
|
9
|
-
end
|
5
|
+
require 'action_view/renderer/collection_renderer'
|
10
6
|
|
11
7
|
class Jbuilder
|
12
|
-
|
13
|
-
extend ActiveSupport::Concern
|
14
|
-
|
15
|
-
class_methods do
|
16
|
-
def supported?
|
17
|
-
superclass.private_method_defined?(:build_rendered_template) && self.superclass.private_method_defined?(:build_rendered_collection)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def build_rendered_template(content, template, layout = nil)
|
24
|
-
super(content || json.attributes!, template)
|
25
|
-
end
|
26
|
-
|
27
|
-
def build_rendered_collection(templates, _spacer)
|
28
|
-
json.merge!(templates.map(&:body))
|
29
|
-
end
|
30
|
-
|
31
|
-
def json
|
32
|
-
@options[:locals].fetch(:json)
|
33
|
-
end
|
34
|
-
|
8
|
+
class CollectionRenderer < ::ActionView::CollectionRenderer # :nodoc:
|
35
9
|
class ScopedIterator < ::SimpleDelegator # :nodoc:
|
36
10
|
include Enumerable
|
37
11
|
|
@@ -40,16 +14,6 @@ class Jbuilder
|
|
40
14
|
@scope = scope
|
41
15
|
end
|
42
16
|
|
43
|
-
# Rails 6.0 support:
|
44
|
-
def each
|
45
|
-
return enum_for(:each) unless block_given?
|
46
|
-
|
47
|
-
__getobj__.each do |object|
|
48
|
-
@scope.call { yield(object) }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# Rails 6.1 support:
|
53
17
|
def each_with_info
|
54
18
|
return enum_for(:each_with_info) unless block_given?
|
55
19
|
|
@@ -60,51 +24,29 @@ class Jbuilder
|
|
60
24
|
end
|
61
25
|
|
62
26
|
private_constant :ScopedIterator
|
63
|
-
end
|
64
|
-
|
65
|
-
if defined?(::ActionView::CollectionRenderer)
|
66
|
-
# Rails 6.1 support:
|
67
|
-
class CollectionRenderer < ::ActionView::CollectionRenderer # :nodoc:
|
68
|
-
include CollectionRenderable
|
69
27
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
private
|
76
|
-
def collection_with_template(view, template, layout, collection)
|
77
|
-
super(view, template, layout, ScopedIterator.new(collection, @scope))
|
78
|
-
end
|
28
|
+
def initialize(lookup_context, options, &scope)
|
29
|
+
super(lookup_context, options)
|
30
|
+
@scope = scope
|
79
31
|
end
|
80
|
-
else
|
81
|
-
# Rails 6.0 support:
|
82
|
-
class CollectionRenderer < ::ActionView::PartialRenderer # :nodoc:
|
83
|
-
include CollectionRenderable
|
84
32
|
|
85
|
-
|
86
|
-
super(lookup_context)
|
87
|
-
@options = options
|
88
|
-
@scope = scope
|
89
|
-
end
|
33
|
+
private
|
90
34
|
|
91
|
-
def
|
92
|
-
|
35
|
+
def build_rendered_template(content, template, layout = nil)
|
36
|
+
super(content || json.attributes!, template)
|
93
37
|
end
|
94
38
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
super(view)
|
100
|
-
end
|
39
|
+
def build_rendered_collection(templates, _spacer)
|
40
|
+
json.merge!(templates.map(&:body))
|
41
|
+
end
|
101
42
|
|
102
|
-
|
103
|
-
|
43
|
+
def json
|
44
|
+
@options[:locals].fetch(:json)
|
45
|
+
end
|
104
46
|
|
105
|
-
|
106
|
-
|
107
|
-
|
47
|
+
def collection_with_template(view, template, layout, collection)
|
48
|
+
super(view, template, layout, ScopedIterator.new(collection, @scope))
|
49
|
+
end
|
108
50
|
end
|
109
51
|
|
110
52
|
class EnumerableCompat < ::SimpleDelegator
|
data/lib/jbuilder/errors.rb
CHANGED
data/lib/jbuilder/jbuilder.rb
CHANGED