jbuilder 2.9.0 → 2.11.2
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/.gitignore +2 -0
- data/.travis.yml +20 -28
- data/Appraisals +11 -13
- data/CHANGELOG.md +50 -0
- data/CONTRIBUTING.md +1 -3
- data/README.md +19 -0
- data/gemfiles/{rails_4_2.gemfile → rails_6_0.gemfile} +1 -1
- data/jbuilder.gemspec +9 -3
- data/lib/generators/rails/jbuilder_generator.rb +4 -0
- data/lib/generators/rails/templates/api_controller.rb +3 -3
- data/lib/generators/rails/templates/controller.rb +13 -18
- data/lib/generators/rails/templates/partial.json.jbuilder +14 -0
- data/lib/jbuilder.rb +63 -22
- data/lib/jbuilder/jbuilder_template.rb +3 -3
- data/test/jbuilder_generator_test.rb +12 -0
- data/test/jbuilder_test.rb +226 -1
- data/test/scaffold_api_controller_generator_test.rb +11 -0
- data/test/scaffold_controller_generator_test.rb +15 -5
- data/test/test_helper.rb +2 -1
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '039b14d174dd7bfb3a5e00d5a315aee89f1efd46a570244191ab985bb44fc328'
|
|
4
|
+
data.tar.gz: 4eda58d10150903687b7940b858fa02c6f0a2cbca8858cd2ae9866c5be5a4b62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d20f2794455635cbb3272bd4b6e8f91781e2c55aa40c7228d5347b4b6ad049cd3cc22ebc9ef708b8bbe4a05811774de07770b175035342123458a4637b9240f
|
|
7
|
+
data.tar.gz: 383aca1c7489eda135339e4538fa8a9dec80900c7c8bab786729a7c323d63f3a75657889ee6dad6bf91b769ced3eb507e41ef7daa15faa8bb3c5d0261c0c0394
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -3,55 +3,47 @@ language: ruby
|
|
|
3
3
|
cache: bundler
|
|
4
4
|
|
|
5
5
|
before_install:
|
|
6
|
-
- "gem update --system 2.7.9"
|
|
7
6
|
- "gem install bundler -v '<2'"
|
|
8
7
|
|
|
9
8
|
rvm:
|
|
10
9
|
- 2.2.10
|
|
11
10
|
- 2.3.8
|
|
12
|
-
- 2.4.
|
|
13
|
-
- 2.5.
|
|
14
|
-
- 2.6.
|
|
11
|
+
- 2.4.10
|
|
12
|
+
- 2.5.8
|
|
13
|
+
- 2.6.6
|
|
14
|
+
- 2.7.1
|
|
15
15
|
- ruby-head
|
|
16
|
-
- rbx-3.107
|
|
17
16
|
|
|
18
17
|
gemfile:
|
|
19
|
-
- gemfiles/rails_4_2.gemfile
|
|
20
18
|
- gemfiles/rails_5_0.gemfile
|
|
21
19
|
- gemfiles/rails_5_1.gemfile
|
|
22
20
|
- gemfiles/rails_5_2.gemfile
|
|
21
|
+
- gemfiles/rails_6_0.gemfile
|
|
23
22
|
- gemfiles/rails_head.gemfile
|
|
24
23
|
|
|
25
24
|
matrix:
|
|
26
|
-
include:
|
|
27
|
-
- rvm: 1.9
|
|
28
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
29
|
-
- rvm: 2.0
|
|
30
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
31
|
-
- rvm: 2.1
|
|
32
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
33
|
-
- rvm: 2.3
|
|
34
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
35
|
-
- rvm: jruby-19mode
|
|
36
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
37
|
-
- rvm: rbx-3.107
|
|
38
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
39
25
|
exclude:
|
|
40
|
-
- rvm: 2.
|
|
41
|
-
gemfile: gemfiles/
|
|
42
|
-
- rvm: 2.
|
|
43
|
-
gemfile: gemfiles/
|
|
44
|
-
- rvm: 2.
|
|
45
|
-
gemfile: gemfiles/
|
|
26
|
+
- rvm: 2.7.1
|
|
27
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
28
|
+
- rvm: 2.7.1
|
|
29
|
+
gemfile: gemfiles/rails_5_1.gemfile
|
|
30
|
+
- rvm: 2.2.10
|
|
31
|
+
gemfile: gemfiles/rails_5_2.gemfile
|
|
32
|
+
- rvm: 2.7.1
|
|
33
|
+
gemfile: gemfiles/rails_5_2.gemfile
|
|
34
|
+
- rvm: 2.2.10
|
|
35
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
|
36
|
+
- rvm: 2.3.8
|
|
37
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
|
38
|
+
- rvm: 2.4.10
|
|
39
|
+
gemfile: gemfiles/rails_6_0.gemfile
|
|
46
40
|
- rvm: 2.2.10
|
|
47
41
|
gemfile: gemfiles/rails_head.gemfile
|
|
48
42
|
- rvm: 2.3.8
|
|
49
43
|
gemfile: gemfiles/rails_head.gemfile
|
|
50
|
-
- rvm: 2.4.
|
|
44
|
+
- rvm: 2.4.10
|
|
51
45
|
gemfile: gemfiles/rails_head.gemfile
|
|
52
46
|
allow_failures:
|
|
53
|
-
- rvm: jruby-19mode
|
|
54
|
-
- rvm: rbx-3.107
|
|
55
47
|
- rvm: ruby-head
|
|
56
48
|
- gemfile: gemfiles/rails_head.gemfile
|
|
57
49
|
fast_finish: true
|
data/Appraisals
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
appraise "rails-
|
|
2
|
-
gem "rails", "~>
|
|
1
|
+
appraise "rails-5-0" do
|
|
2
|
+
gem "rails", "~> 5.0.0"
|
|
3
3
|
end
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
appraise "rails-5-1" do
|
|
11
|
-
gem "rails", "~> 5.1.0"
|
|
12
|
-
end
|
|
5
|
+
appraise "rails-5-1" do
|
|
6
|
+
gem "rails", "~> 5.1.0"
|
|
7
|
+
end
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end
|
|
9
|
+
appraise "rails-5-2" do
|
|
10
|
+
gem "rails", "~> 5.2.0"
|
|
17
11
|
end
|
|
18
12
|
|
|
19
13
|
if RUBY_VERSION >= "2.5.0"
|
|
14
|
+
appraise "rails-6-0" do
|
|
15
|
+
gem "rails", "~> 6.0.0"
|
|
16
|
+
end
|
|
17
|
+
|
|
20
18
|
appraise "rails-head" do
|
|
21
19
|
gem "rails", github: "rails/rails"
|
|
22
20
|
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
2.11.2
|
|
4
|
+
------
|
|
5
|
+
|
|
6
|
+
* [Improve key formatting for nested hashes and disable by default](https://github.com/rails/jbuilder/pull/497)
|
|
7
|
+
|
|
8
|
+
2.11.1
|
|
9
|
+
------
|
|
10
|
+
|
|
11
|
+
* Use symbols instead of strings for before_action filters [DHH]
|
|
12
|
+
* Slim down comments in generated scaffold code [DHH]
|
|
13
|
+
|
|
14
|
+
2.11.0
|
|
15
|
+
------
|
|
16
|
+
|
|
17
|
+
* [Allow jbuilder instance to be passed to #merge!](https://github.com/rails/jbuilder/pull/485)
|
|
18
|
+
* [Fix for key_format! when using nested hashes](https://github.com/rails/jbuilder/pull/486)
|
|
19
|
+
* [Include rich_text, attachment, and attachments fields in json partial](https://github.com/rails/jbuilder/pull/459)
|
|
20
|
+
|
|
21
|
+
2.10.2
|
|
22
|
+
------
|
|
23
|
+
|
|
24
|
+
* Update scaffold generator to use double quotes, 422 form error responds, and modern string-of-arrays syntax [DHH]
|
|
25
|
+
|
|
26
|
+
2.10.1
|
|
27
|
+
------
|
|
28
|
+
|
|
29
|
+
* Fix keyword arguments warning on Ruby 2.7
|
|
30
|
+
|
|
31
|
+
2.10.0
|
|
32
|
+
------
|
|
33
|
+
|
|
34
|
+
* Requires Rails 5+ and Ruby 2.2+
|
|
35
|
+
* Nested hashes are deep-merged
|
|
36
|
+
|
|
37
|
+
2.9.1
|
|
38
|
+
-----
|
|
39
|
+
|
|
40
|
+
* [Respect JSON encoding customizations](https://github.com/rails/jbuilder/commit/e2e8623b08078ad6a2323ce8ecaf642b7afe1166)
|
|
41
|
+
|
|
42
|
+
2.9.0
|
|
43
|
+
-----
|
|
44
|
+
|
|
45
|
+
* [Fix passing object with partial without locals](https://github.com/rails/jbuilder/pull/435)
|
|
46
|
+
* [Fix deprecation warning in Rails 6.0](https://github.com/rails/jbuilder/pull/453)
|
|
47
|
+
* [Use quotes consistently in generated templates](https://github.com/rails/jbuilder/pull/455)
|
|
48
|
+
* [Allow omitting timestamps from generated partials](https://github.com/rails/jbuilder/pull/448)
|
|
49
|
+
* [Respect changing scaffold generator](https://github.com/rails/jbuilder/pull/458)
|
|
50
|
+
* [Use a symbolic default format for Rails 6.0 forward compatibility](https://github.com/rails/jbuilder/commit/3895a7243f3db292b0bf15513fc05494e6e50576)
|
|
51
|
+
* [Drop MultiJSON in favor of Ruby standard library JSON](https://github.com/rails/jbuilder/commit/b952ae096eb1828b0fcfde06e6ba62311494ec49)
|
|
52
|
+
|
|
3
53
|
2.8.0
|
|
4
54
|
-----
|
|
5
55
|
|
data/CONTRIBUTING.md
CHANGED
|
@@ -4,18 +4,16 @@ Contributing to Jbuilder
|
|
|
4
4
|
[][travis]
|
|
5
5
|
[][gem]
|
|
6
6
|
[][codeclimate]
|
|
7
|
-
[][gemnasium]
|
|
8
7
|
|
|
9
8
|
[travis]: https://travis-ci.org/rails/jbuilder
|
|
10
9
|
[gem]: https://rubygems.org/gems/jbuilder
|
|
11
10
|
[codeclimate]: https://codeclimate.com/github/rails/jbuilder
|
|
12
|
-
[gemnasium]: https://gemnasium.com/rails/jbuilder
|
|
13
11
|
|
|
14
12
|
Jbuilder is work of [many contributors](https://github.com/rails/jbuilder/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/jbuilder/pulls), [propose features and discuss issues](https://github.com/rails/jbuilder/issues).
|
|
15
13
|
|
|
16
14
|
#### Fork the Project
|
|
17
15
|
|
|
18
|
-
Fork the [project on
|
|
16
|
+
Fork the [project on GitHub](https://github.com/rails/jbuilder) and check out your copy.
|
|
19
17
|
|
|
20
18
|
```
|
|
21
19
|
git clone https://github.com/contributor/jbuilder.git
|
data/README.md
CHANGED
|
@@ -274,6 +274,25 @@ environment.rb for example):
|
|
|
274
274
|
Jbuilder.key_format camelize: :lower
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
+
By default, key format is not applied to keys of hashes that are
|
|
278
|
+
passed to methods like `set!`, `array!` or `merge!`. You can opt into
|
|
279
|
+
deeply transforming these as well:
|
|
280
|
+
|
|
281
|
+
``` ruby
|
|
282
|
+
json.key_format! camelize: :lower
|
|
283
|
+
json.deep_format_keys!
|
|
284
|
+
json.settings([{some_value: "abc"}])
|
|
285
|
+
|
|
286
|
+
# => { "settings": [{ "someValue": "abc" }]}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
You can set this globally with the class method `deep_format_keys` (from inside your
|
|
290
|
+
environment.rb for example):
|
|
291
|
+
|
|
292
|
+
``` ruby
|
|
293
|
+
Jbuilder.deep_format_keys true
|
|
294
|
+
```
|
|
295
|
+
|
|
277
296
|
## Contributing to Jbuilder
|
|
278
297
|
|
|
279
298
|
Jbuilder is the work of many contributors. You're encouraged to submit pull requests, propose
|
data/jbuilder.gemspec
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'jbuilder'
|
|
3
|
-
s.version = '2.
|
|
3
|
+
s.version = '2.11.2'
|
|
4
4
|
s.authors = 'David Heinemeier Hansson'
|
|
5
5
|
s.email = 'david@basecamp.com'
|
|
6
6
|
s.summary = 'Create JSON structures via a Builder-style DSL'
|
|
7
7
|
s.homepage = 'https://github.com/rails/jbuilder'
|
|
8
8
|
s.license = 'MIT'
|
|
9
9
|
|
|
10
|
-
s.required_ruby_version = '>=
|
|
10
|
+
s.required_ruby_version = '>= 2.2.2'
|
|
11
11
|
|
|
12
|
-
s.add_dependency 'activesupport', '>=
|
|
12
|
+
s.add_dependency 'activesupport', '>= 5.0.0'
|
|
13
|
+
|
|
14
|
+
if RUBY_ENGINE == 'rbx'
|
|
15
|
+
s.add_development_dependency('racc')
|
|
16
|
+
s.add_development_dependency('json')
|
|
17
|
+
s.add_development_dependency('rubysl')
|
|
18
|
+
end
|
|
13
19
|
|
|
14
20
|
s.files = `git ls-files`.split("\n")
|
|
15
21
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<% if namespaced? -%>
|
|
2
|
-
require_dependency "<%=
|
|
2
|
+
require_dependency "<%= namespaced_path %>/application_controller"
|
|
3
3
|
|
|
4
4
|
<% end -%>
|
|
5
5
|
<% module_namespacing do -%>
|
|
6
6
|
class <%= controller_class_name %>Controller < ApplicationController
|
|
7
|
-
before_action :set_<%= singular_table_name %>, only: [
|
|
7
|
+
before_action :set_<%= singular_table_name %>, only: %i[ show update destroy ]
|
|
8
8
|
|
|
9
9
|
# GET <%= route_url %>
|
|
10
10
|
# GET <%= route_url %>.json
|
|
@@ -51,7 +51,7 @@ class <%= controller_class_name %>Controller < ApplicationController
|
|
|
51
51
|
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
#
|
|
54
|
+
# Only allow a list of trusted parameters through.
|
|
55
55
|
def <%= "#{singular_table_name}_params" %>
|
|
56
56
|
<%- if attributes_names.empty? -%>
|
|
57
57
|
params.fetch(<%= ":#{singular_table_name}" %>, {})
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
<% if namespaced? -%>
|
|
2
|
-
require_dependency "<%=
|
|
2
|
+
require_dependency "<%= namespaced_path %>/application_controller"
|
|
3
3
|
|
|
4
4
|
<% end -%>
|
|
5
5
|
<% module_namespacing do -%>
|
|
6
6
|
class <%= controller_class_name %>Controller < ApplicationController
|
|
7
|
-
before_action :set_<%= singular_table_name %>, only: [
|
|
7
|
+
before_action :set_<%= singular_table_name %>, only: %i[ show edit update destroy ]
|
|
8
8
|
|
|
9
|
-
# GET <%= route_url %>
|
|
10
|
-
# GET <%= route_url %>.json
|
|
9
|
+
# GET <%= route_url %> or <%= route_url %>.json
|
|
11
10
|
def index
|
|
12
11
|
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
|
|
13
12
|
end
|
|
14
13
|
|
|
15
|
-
# GET <%= route_url %>/1
|
|
16
|
-
# GET <%= route_url %>/1.json
|
|
14
|
+
# GET <%= route_url %>/1 or <%= route_url %>/1.json
|
|
17
15
|
def show
|
|
18
16
|
end
|
|
19
17
|
|
|
@@ -26,42 +24,39 @@ class <%= controller_class_name %>Controller < ApplicationController
|
|
|
26
24
|
def edit
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
# POST <%= route_url %>
|
|
30
|
-
# POST <%= route_url %>.json
|
|
27
|
+
# POST <%= route_url %> or <%= route_url %>.json
|
|
31
28
|
def create
|
|
32
29
|
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
|
|
33
30
|
|
|
34
31
|
respond_to do |format|
|
|
35
32
|
if @<%= orm_instance.save %>
|
|
36
|
-
format.html { redirect_to @<%= singular_table_name %>, notice: <%= "
|
|
33
|
+
format.html { redirect_to @<%= singular_table_name %>, notice: <%= %("#{human_name} was successfully created.") %> }
|
|
37
34
|
format.json { render :show, status: :created, location: <%= "@#{singular_table_name}" %> }
|
|
38
35
|
else
|
|
39
|
-
format.html { render :new }
|
|
36
|
+
format.html { render :new, status: :unprocessable_entity }
|
|
40
37
|
format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
|
|
41
38
|
end
|
|
42
39
|
end
|
|
43
40
|
end
|
|
44
41
|
|
|
45
|
-
# PATCH/PUT <%= route_url %>/1
|
|
46
|
-
# PATCH/PUT <%= route_url %>/1.json
|
|
42
|
+
# PATCH/PUT <%= route_url %>/1 or <%= route_url %>/1.json
|
|
47
43
|
def update
|
|
48
44
|
respond_to do |format|
|
|
49
45
|
if @<%= orm_instance.update("#{singular_table_name}_params") %>
|
|
50
|
-
format.html { redirect_to @<%= singular_table_name %>, notice: <%= "
|
|
46
|
+
format.html { redirect_to @<%= singular_table_name %>, notice: <%= %("#{human_name} was successfully updated.") %> }
|
|
51
47
|
format.json { render :show, status: :ok, location: <%= "@#{singular_table_name}" %> }
|
|
52
48
|
else
|
|
53
|
-
format.html { render :edit }
|
|
49
|
+
format.html { render :edit, status: :unprocessable_entity }
|
|
54
50
|
format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
|
|
55
51
|
end
|
|
56
52
|
end
|
|
57
53
|
end
|
|
58
54
|
|
|
59
|
-
# DELETE <%= route_url %>/1
|
|
60
|
-
# DELETE <%= route_url %>/1.json
|
|
55
|
+
# DELETE <%= route_url %>/1 or <%= route_url %>/1.json
|
|
61
56
|
def destroy
|
|
62
57
|
@<%= orm_instance.destroy %>
|
|
63
58
|
respond_to do |format|
|
|
64
|
-
format.html { redirect_to <%= index_helper %>_url, notice: <%= "
|
|
59
|
+
format.html { redirect_to <%= index_helper %>_url, notice: <%= %("#{human_name} was successfully destroyed.") %> }
|
|
65
60
|
format.json { head :no_content }
|
|
66
61
|
end
|
|
67
62
|
end
|
|
@@ -72,7 +67,7 @@ class <%= controller_class_name %>Controller < ApplicationController
|
|
|
72
67
|
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
|
73
68
|
end
|
|
74
69
|
|
|
75
|
-
#
|
|
70
|
+
# Only allow a list of trusted parameters through.
|
|
76
71
|
def <%= "#{singular_table_name}_params" %>
|
|
77
72
|
<%- if attributes_names.empty? -%>
|
|
78
73
|
params.fetch(<%= ":#{singular_table_name}" %>, {})
|
|
@@ -1,2 +1,16 @@
|
|
|
1
1
|
json.extract! <%= singular_table_name %>, <%= full_attributes_list %>
|
|
2
2
|
json.url <%= singular_table_name %>_url(<%= singular_table_name %>, format: :json)
|
|
3
|
+
<%- virtual_attributes.each do |attribute| -%>
|
|
4
|
+
<%- if attribute.type == :rich_text -%>
|
|
5
|
+
json.<%= attribute.name %> <%= singular_table_name %>.<%= attribute.name %>.to_s
|
|
6
|
+
<%- elsif attribute.type == :attachment -%>
|
|
7
|
+
json.<%= attribute.name %> url_for(<%= singular_table_name %>.<%= attribute.name %>)
|
|
8
|
+
<%- elsif attribute.type == :attachments -%>
|
|
9
|
+
json.<%= attribute.name %> do
|
|
10
|
+
json.array!(<%= singular_table_name %>.<%= attribute.name %>) do |<%= attribute.singular_name %>|
|
|
11
|
+
json.id <%= attribute.singular_name %>.id
|
|
12
|
+
json.url url_for(<%= attribute.singular_name %>)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
<%- end -%>
|
|
16
|
+
<%- end -%>
|
data/lib/jbuilder.rb
CHANGED
|
@@ -4,16 +4,19 @@ require 'jbuilder/key_formatter'
|
|
|
4
4
|
require 'jbuilder/errors'
|
|
5
5
|
require 'json'
|
|
6
6
|
require 'ostruct'
|
|
7
|
+
require 'active_support/core_ext/hash/deep_merge'
|
|
7
8
|
|
|
8
9
|
class Jbuilder
|
|
9
10
|
@@key_formatter = nil
|
|
10
11
|
@@ignore_nil = false
|
|
12
|
+
@@deep_format_keys = false
|
|
11
13
|
|
|
12
14
|
def initialize(options = {})
|
|
13
15
|
@attributes = {}
|
|
14
16
|
|
|
15
17
|
@key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
|
|
16
18
|
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
|
|
19
|
+
@deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys)
|
|
17
20
|
|
|
18
21
|
yield self if ::Kernel.block_given?
|
|
19
22
|
end
|
|
@@ -26,12 +29,12 @@ class Jbuilder
|
|
|
26
29
|
BLANK = Blank.new
|
|
27
30
|
NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set
|
|
28
31
|
|
|
29
|
-
def set!(key, value = BLANK, *args)
|
|
32
|
+
def set!(key, value = BLANK, *args, &block)
|
|
30
33
|
result = if ::Kernel.block_given?
|
|
31
34
|
if !_blank?(value)
|
|
32
35
|
# json.comments @post.comments { |comment| ... }
|
|
33
36
|
# { "comments": [ { ... }, { ... } ] }
|
|
34
|
-
_scope{ array! value,
|
|
37
|
+
_scope{ array! value, &block }
|
|
35
38
|
else
|
|
36
39
|
# json.comments { ... }
|
|
37
40
|
# { "comments": ... }
|
|
@@ -42,11 +45,11 @@ class Jbuilder
|
|
|
42
45
|
# json.age 32
|
|
43
46
|
# json.person another_jbuilder
|
|
44
47
|
# { "age": 32, "person": { ... }
|
|
45
|
-
value.attributes!
|
|
48
|
+
_format_keys(value.attributes!)
|
|
46
49
|
else
|
|
47
50
|
# json.age 32
|
|
48
51
|
# { "age": 32 }
|
|
49
|
-
value
|
|
52
|
+
_format_keys(value)
|
|
50
53
|
end
|
|
51
54
|
elsif _is_collection?(value)
|
|
52
55
|
# json.comments @post.comments, :content, :created_at
|
|
@@ -61,9 +64,9 @@ class Jbuilder
|
|
|
61
64
|
_set_value key, result
|
|
62
65
|
end
|
|
63
66
|
|
|
64
|
-
def method_missing(*args)
|
|
67
|
+
def method_missing(*args, &block)
|
|
65
68
|
if ::Kernel.block_given?
|
|
66
|
-
set!(*args,
|
|
69
|
+
set!(*args, &block)
|
|
67
70
|
else
|
|
68
71
|
set!(*args)
|
|
69
72
|
end
|
|
@@ -130,6 +133,31 @@ class Jbuilder
|
|
|
130
133
|
@@ignore_nil = value
|
|
131
134
|
end
|
|
132
135
|
|
|
136
|
+
# Deeply apply key format to nested hashes and arrays passed to
|
|
137
|
+
# methods like set!, merge! or array!.
|
|
138
|
+
#
|
|
139
|
+
# Example:
|
|
140
|
+
#
|
|
141
|
+
# json.key_format! camelize: :lower
|
|
142
|
+
# json.settings({some_value: "abc"})
|
|
143
|
+
#
|
|
144
|
+
# { "settings": { "some_value": "abc" }}
|
|
145
|
+
#
|
|
146
|
+
# json.key_format! camelize: :lower
|
|
147
|
+
# json.deep_format_keys!
|
|
148
|
+
# json.settings({some_value: "abc"})
|
|
149
|
+
#
|
|
150
|
+
# { "settings": { "someValue": "abc" }}
|
|
151
|
+
#
|
|
152
|
+
def deep_format_keys!(value = true)
|
|
153
|
+
@deep_format_keys = value
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Same as instance method deep_format_keys! except sets the default.
|
|
157
|
+
def self.deep_format_keys(value = true)
|
|
158
|
+
@@deep_format_keys = value
|
|
159
|
+
end
|
|
160
|
+
|
|
133
161
|
# Turns the current element into an array and yields a builder to add a hash.
|
|
134
162
|
#
|
|
135
163
|
# Example:
|
|
@@ -163,7 +191,7 @@ class Jbuilder
|
|
|
163
191
|
#
|
|
164
192
|
# [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ]
|
|
165
193
|
#
|
|
166
|
-
#
|
|
194
|
+
# You can use the call syntax instead of an explicit extract! call:
|
|
167
195
|
#
|
|
168
196
|
# json.(@people) { |person| ... }
|
|
169
197
|
#
|
|
@@ -181,18 +209,18 @@ class Jbuilder
|
|
|
181
209
|
# json.array! [1, 2, 3]
|
|
182
210
|
#
|
|
183
211
|
# [1,2,3]
|
|
184
|
-
def array!(collection = [], *attributes)
|
|
212
|
+
def array!(collection = [], *attributes, &block)
|
|
185
213
|
array = if collection.nil?
|
|
186
214
|
[]
|
|
187
215
|
elsif ::Kernel.block_given?
|
|
188
|
-
_map_collection(collection,
|
|
216
|
+
_map_collection(collection, &block)
|
|
189
217
|
elsif attributes.any?
|
|
190
218
|
_map_collection(collection) { |element| extract! element, *attributes }
|
|
191
219
|
else
|
|
192
|
-
collection.to_a
|
|
220
|
+
_format_keys(collection.to_a)
|
|
193
221
|
end
|
|
194
222
|
|
|
195
|
-
|
|
223
|
+
@attributes = _merge_values(@attributes, array)
|
|
196
224
|
end
|
|
197
225
|
|
|
198
226
|
# Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
|
|
@@ -220,9 +248,9 @@ class Jbuilder
|
|
|
220
248
|
end
|
|
221
249
|
end
|
|
222
250
|
|
|
223
|
-
def call(object, *attributes)
|
|
251
|
+
def call(object, *attributes, &block)
|
|
224
252
|
if ::Kernel.block_given?
|
|
225
|
-
array! object,
|
|
253
|
+
array! object, &block
|
|
226
254
|
else
|
|
227
255
|
extract! object, *attributes
|
|
228
256
|
end
|
|
@@ -240,24 +268,25 @@ class Jbuilder
|
|
|
240
268
|
@attributes
|
|
241
269
|
end
|
|
242
270
|
|
|
243
|
-
# Merges hash or
|
|
244
|
-
def merge!(
|
|
245
|
-
|
|
271
|
+
# Merges hash, array, or Jbuilder instance into current builder.
|
|
272
|
+
def merge!(object)
|
|
273
|
+
hash_or_array = ::Jbuilder === object ? object.attributes! : object
|
|
274
|
+
@attributes = _merge_values(@attributes, _format_keys(hash_or_array))
|
|
246
275
|
end
|
|
247
276
|
|
|
248
277
|
# Encodes the current builder as JSON.
|
|
249
278
|
def target!
|
|
250
|
-
|
|
279
|
+
@attributes.to_json
|
|
251
280
|
end
|
|
252
281
|
|
|
253
282
|
private
|
|
254
283
|
|
|
255
284
|
def _extract_hash_values(object, attributes)
|
|
256
|
-
attributes.each{ |key| _set_value key, object.fetch(key) }
|
|
285
|
+
attributes.each{ |key| _set_value key, _format_keys(object.fetch(key)) }
|
|
257
286
|
end
|
|
258
287
|
|
|
259
288
|
def _extract_method_values(object, attributes)
|
|
260
|
-
attributes.each{ |key| _set_value key, object.public_send(key) }
|
|
289
|
+
attributes.each{ |key| _set_value key, _format_keys(object.public_send(key)) }
|
|
261
290
|
end
|
|
262
291
|
|
|
263
292
|
def _merge_block(key)
|
|
@@ -275,7 +304,7 @@ class Jbuilder
|
|
|
275
304
|
elsif ::Array === current_value && ::Array === updates
|
|
276
305
|
current_value + updates
|
|
277
306
|
elsif ::Hash === current_value && ::Hash === updates
|
|
278
|
-
current_value.
|
|
307
|
+
current_value.deep_merge(updates)
|
|
279
308
|
else
|
|
280
309
|
raise MergeError.build(current_value, updates)
|
|
281
310
|
end
|
|
@@ -285,6 +314,18 @@ class Jbuilder
|
|
|
285
314
|
@key_formatter ? @key_formatter.format(key) : key.to_s
|
|
286
315
|
end
|
|
287
316
|
|
|
317
|
+
def _format_keys(hash_or_array)
|
|
318
|
+
return hash_or_array unless @deep_format_keys
|
|
319
|
+
|
|
320
|
+
if ::Array === hash_or_array
|
|
321
|
+
hash_or_array.map { |value| _format_keys(value) }
|
|
322
|
+
elsif ::Hash === hash_or_array
|
|
323
|
+
::Hash[hash_or_array.collect { |k, v| [_key(k), _format_keys(v)] }]
|
|
324
|
+
else
|
|
325
|
+
hash_or_array
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
288
329
|
def _set_value(key, value)
|
|
289
330
|
raise NullError.build(key) if @attributes.nil?
|
|
290
331
|
raise ArrayError.build(key) if ::Array === @attributes
|
|
@@ -300,12 +341,12 @@ class Jbuilder
|
|
|
300
341
|
end
|
|
301
342
|
|
|
302
343
|
def _scope
|
|
303
|
-
parent_attributes, parent_formatter = @attributes, @key_formatter
|
|
344
|
+
parent_attributes, parent_formatter, parent_deep_format_keys = @attributes, @key_formatter, @deep_format_keys
|
|
304
345
|
@attributes = BLANK
|
|
305
346
|
yield
|
|
306
347
|
@attributes
|
|
307
348
|
ensure
|
|
308
|
-
@attributes, @key_formatter = parent_attributes, parent_formatter
|
|
349
|
+
@attributes, @key_formatter, @deep_format_keys = parent_attributes, parent_formatter, parent_deep_format_keys
|
|
309
350
|
end
|
|
310
351
|
|
|
311
352
|
def _is_collection?(object)
|
|
@@ -73,8 +73,8 @@ class JbuilderTemplate < Jbuilder
|
|
|
73
73
|
# json.cache_if! !admin?, @person, expires_in: 10.minutes do
|
|
74
74
|
# json.extract! @person, :name, :age
|
|
75
75
|
# end
|
|
76
|
-
def cache_if!(condition, *args)
|
|
77
|
-
condition ? cache!(*args,
|
|
76
|
+
def cache_if!(condition, *args, &block)
|
|
77
|
+
condition ? cache!(*args, &block) : yield
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def target!
|
|
@@ -164,7 +164,7 @@ class JbuilderTemplate < Jbuilder
|
|
|
164
164
|
if @context.respond_to?(:cache_fragment_name)
|
|
165
165
|
# Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
|
|
166
166
|
# should be used instead.
|
|
167
|
-
@context.cache_fragment_name(key, options)
|
|
167
|
+
@context.cache_fragment_name(key, **options)
|
|
168
168
|
elsif @context.respond_to?(:fragment_name_with_digest)
|
|
169
169
|
# Backwards compatibility for period of time when fragment_name_with_digest was made public.
|
|
170
170
|
@context.fragment_name_with_digest(key)
|
|
@@ -43,4 +43,16 @@ class JbuilderGeneratorTest < Rails::Generators::TestCase
|
|
|
43
43
|
assert_no_match %r{:created_at, :updated_at}, content
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
+
|
|
47
|
+
if Rails::VERSION::MAJOR >= 6
|
|
48
|
+
test 'handles virtual attributes' do
|
|
49
|
+
run_generator %w(Message content:rich_text video:attachment photos:attachments)
|
|
50
|
+
|
|
51
|
+
assert_file 'app/views/messages/_message.json.jbuilder' do |content|
|
|
52
|
+
assert_match %r{json\.content message\.content\.to_s}, content
|
|
53
|
+
assert_match %r{json\.video url_for\(message\.video\)}, content
|
|
54
|
+
assert_match %r{json\.photos do\n json\.array!\(message\.photos\) do \|photo\|\n json\.id photo\.id\n json\.url url_for\(photo\)\n end\nend}, content
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
46
58
|
end
|
data/test/jbuilder_test.rb
CHANGED
|
@@ -99,7 +99,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
99
99
|
assert_equal 32, result['age']
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
-
test 'extracting from object using call style
|
|
102
|
+
test 'extracting from object using call style' do
|
|
103
103
|
person = Struct.new(:name, :age).new('David', 32)
|
|
104
104
|
|
|
105
105
|
result = jbuild do |json|
|
|
@@ -159,6 +159,25 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
159
159
|
assert_equal 32, result['author']['age']
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
+
test 'nested blocks are additive' do
|
|
163
|
+
result = jbuild do |json|
|
|
164
|
+
json.author do
|
|
165
|
+
json.name do
|
|
166
|
+
json.first 'David'
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
json.author do
|
|
171
|
+
json.name do
|
|
172
|
+
json.last 'Heinemeier Hansson'
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
assert_equal 'David', result['author']['name']['first']
|
|
178
|
+
assert_equal 'Heinemeier Hansson', result['author']['name']['last']
|
|
179
|
+
end
|
|
180
|
+
|
|
162
181
|
test 'support merge! method' do
|
|
163
182
|
result = jbuild do |json|
|
|
164
183
|
json.merge! 'foo' => 'bar'
|
|
@@ -177,6 +196,18 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
177
196
|
assert_equal 'Pavel', result['author']['name']
|
|
178
197
|
end
|
|
179
198
|
|
|
199
|
+
test 'support merge! method with Jbuilder instance' do
|
|
200
|
+
obj = jbuild do |json|
|
|
201
|
+
json.foo 'bar'
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
result = jbuild do |json|
|
|
205
|
+
json.merge! obj
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
assert_equal 'bar', result['foo']
|
|
209
|
+
end
|
|
210
|
+
|
|
180
211
|
test 'blocks are additive via extract syntax' do
|
|
181
212
|
person = Person.new('Pavel', 27)
|
|
182
213
|
|
|
@@ -535,6 +566,36 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
535
566
|
assert_equal 'one', result['level1']
|
|
536
567
|
end
|
|
537
568
|
|
|
569
|
+
test 'key_format! can be changed in child elements' do
|
|
570
|
+
result = jbuild do |json|
|
|
571
|
+
json.key_format! camelize: :lower
|
|
572
|
+
|
|
573
|
+
json.level_one do
|
|
574
|
+
json.key_format! :upcase
|
|
575
|
+
json.value 'two'
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
assert_equal ['levelOne'], result.keys
|
|
580
|
+
assert_equal ['VALUE'], result['levelOne'].keys
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
test 'key_format! can be changed in array!' do
|
|
584
|
+
result = jbuild do |json|
|
|
585
|
+
json.key_format! camelize: :lower
|
|
586
|
+
|
|
587
|
+
json.level_one do
|
|
588
|
+
json.array! [{value: 'two'}] do |object|
|
|
589
|
+
json.key_format! :upcase
|
|
590
|
+
json.value object[:value]
|
|
591
|
+
end
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
assert_equal ['levelOne'], result.keys
|
|
596
|
+
assert_equal ['VALUE'], result['levelOne'][0].keys
|
|
597
|
+
end
|
|
598
|
+
|
|
538
599
|
test 'key_format! with no parameter' do
|
|
539
600
|
result = jbuild do |json|
|
|
540
601
|
json.key_format! :upcase
|
|
@@ -562,6 +623,161 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
562
623
|
assert_equal ['oats and friends'], result.keys
|
|
563
624
|
end
|
|
564
625
|
|
|
626
|
+
test 'key_format! is not applied deeply by default' do
|
|
627
|
+
names = { first_name: 'camel', last_name: 'case' }
|
|
628
|
+
result = jbuild do |json|
|
|
629
|
+
json.key_format! camelize: :lower
|
|
630
|
+
json.set! :all_names, names
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
assert_equal %i[first_name last_name], result['allNames'].keys
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
test 'applying key_format! deeply can be enabled per scope' do
|
|
637
|
+
names = { first_name: 'camel', last_name: 'case' }
|
|
638
|
+
result = jbuild do |json|
|
|
639
|
+
json.key_format! camelize: :lower
|
|
640
|
+
json.scope do
|
|
641
|
+
json.deep_format_keys!
|
|
642
|
+
json.set! :all_names, names
|
|
643
|
+
end
|
|
644
|
+
json.set! :all_names, names
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
assert_equal %w[firstName lastName], result['scope']['allNames'].keys
|
|
648
|
+
assert_equal %i[first_name last_name], result['allNames'].keys
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
test 'applying key_format! deeply can be disabled per scope' do
|
|
652
|
+
names = { first_name: 'camel', last_name: 'case' }
|
|
653
|
+
result = jbuild do |json|
|
|
654
|
+
json.key_format! camelize: :lower
|
|
655
|
+
json.deep_format_keys!
|
|
656
|
+
json.set! :all_names, names
|
|
657
|
+
json.scope do
|
|
658
|
+
json.deep_format_keys! false
|
|
659
|
+
json.set! :all_names, names
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
assert_equal %w[firstName lastName], result['allNames'].keys
|
|
664
|
+
assert_equal %i[first_name last_name], result['scope']['allNames'].keys
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
test 'applying key_format! deeply can be enabled globally' do
|
|
668
|
+
names = { first_name: 'camel', last_name: 'case' }
|
|
669
|
+
|
|
670
|
+
Jbuilder.deep_format_keys true
|
|
671
|
+
result = jbuild do |json|
|
|
672
|
+
json.key_format! camelize: :lower
|
|
673
|
+
json.set! :all_names, names
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
assert_equal %w[firstName lastName], result['allNames'].keys
|
|
677
|
+
Jbuilder.send(:class_variable_set, '@@deep_format_keys', false)
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
test 'deep key_format! with merge!' do
|
|
681
|
+
hash = { camel_style: 'for JS' }
|
|
682
|
+
result = jbuild do |json|
|
|
683
|
+
json.key_format! camelize: :lower
|
|
684
|
+
json.deep_format_keys!
|
|
685
|
+
json.merge! hash
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
assert_equal ['camelStyle'], result.keys
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
test 'deep key_format! with merge! deep' do
|
|
692
|
+
hash = { camel_style: { sub_attr: 'for JS' } }
|
|
693
|
+
result = jbuild do |json|
|
|
694
|
+
json.key_format! camelize: :lower
|
|
695
|
+
json.deep_format_keys!
|
|
696
|
+
json.merge! hash
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
assert_equal ['subAttr'], result['camelStyle'].keys
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
test 'deep key_format! with set! array of hashes' do
|
|
703
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
704
|
+
result = jbuild do |json|
|
|
705
|
+
json.key_format! camelize: :lower
|
|
706
|
+
json.deep_format_keys!
|
|
707
|
+
json.set! :names, names
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
assert_equal %w[firstName lastName], result['names'][0].keys
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
test 'deep key_format! with set! extracting hash from object' do
|
|
714
|
+
comment = Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })
|
|
715
|
+
result = jbuild do |json|
|
|
716
|
+
json.key_format! camelize: :lower
|
|
717
|
+
json.deep_format_keys!
|
|
718
|
+
json.set! :comment, comment, :author
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
assert_equal %w[firstName lastName], result['comment']['author'].keys
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
test 'deep key_format! with array! of hashes' do
|
|
725
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
726
|
+
result = jbuild do |json|
|
|
727
|
+
json.key_format! camelize: :lower
|
|
728
|
+
json.deep_format_keys!
|
|
729
|
+
json.array! names
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
assert_equal %w[firstName lastName], result[0].keys
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
test 'deep key_format! with merge! array of hashes' do
|
|
736
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
737
|
+
new_names = [{ first_name: 'snake', last_name: 'case' }]
|
|
738
|
+
result = jbuild do |json|
|
|
739
|
+
json.key_format! camelize: :lower
|
|
740
|
+
json.deep_format_keys!
|
|
741
|
+
json.array! names
|
|
742
|
+
json.merge! new_names
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
assert_equal %w[firstName lastName], result[1].keys
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
test 'deep key_format! is applied to hash extracted from object' do
|
|
749
|
+
comment = Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })
|
|
750
|
+
result = jbuild do |json|
|
|
751
|
+
json.key_format! camelize: :lower
|
|
752
|
+
json.deep_format_keys!
|
|
753
|
+
json.extract! comment, :author
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
assert_equal %w[firstName lastName], result['author'].keys
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
test 'deep key_format! is applied to hash extracted from hash' do
|
|
760
|
+
comment = {author: { first_name: 'camel', last_name: 'case' }}
|
|
761
|
+
result = jbuild do |json|
|
|
762
|
+
json.key_format! camelize: :lower
|
|
763
|
+
json.deep_format_keys!
|
|
764
|
+
json.extract! comment, :author
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
assert_equal %w[firstName lastName], result['author'].keys
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
test 'deep key_format! is applied to hash extracted directly from array' do
|
|
771
|
+
comments = [Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })]
|
|
772
|
+
result = jbuild do |json|
|
|
773
|
+
json.key_format! camelize: :lower
|
|
774
|
+
json.deep_format_keys!
|
|
775
|
+
json.array! comments, :author
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
assert_equal %w[firstName lastName], result[0]['author'].keys
|
|
779
|
+
end
|
|
780
|
+
|
|
565
781
|
test 'default key_format!' do
|
|
566
782
|
Jbuilder.key_format camelize: :lower
|
|
567
783
|
result = jbuild{ |json| json.camel_style 'for JS' }
|
|
@@ -713,4 +929,13 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
713
929
|
end
|
|
714
930
|
end
|
|
715
931
|
end
|
|
932
|
+
|
|
933
|
+
if RUBY_VERSION >= "2.2.10"
|
|
934
|
+
test "respects JSON encoding customizations" do
|
|
935
|
+
# Active Support overrides Time#as_json for custom formatting.
|
|
936
|
+
# Ensure we call #to_json on the final attributes instead of JSON.dump.
|
|
937
|
+
result = JSON.load(Jbuilder.encode { |json| json.time Time.parse("2018-05-13 11:51:00.485 -0400") })
|
|
938
|
+
assert_equal "2018-05-13T11:51:00.485-04:00", result["time"]
|
|
939
|
+
end
|
|
940
|
+
end
|
|
716
941
|
end
|
|
@@ -55,5 +55,16 @@ if Rails::VERSION::MAJOR > 4
|
|
|
55
55
|
assert_match %r{params\.fetch\(:post, \{\}\)}, content
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if Rails::VERSION::MAJOR >= 6
|
|
61
|
+
test 'handles virtual attributes' do
|
|
62
|
+
run_generator ["Message", "content:rich_text", "video:attachment", "photos:attachments"]
|
|
63
|
+
|
|
64
|
+
assert_file 'app/controllers/messages_controller.rb' do |content|
|
|
65
|
+
assert_match %r{params\.require\(:message\)\.permit\(:content, :video, photos: \[\]\)}, content
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
58
69
|
end
|
|
59
70
|
end
|
|
@@ -31,22 +31,22 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
|
|
|
31
31
|
assert_instance_method :create, content do |m|
|
|
32
32
|
assert_match %r{@post = Post\.new\(post_params\)}, m
|
|
33
33
|
assert_match %r{@post\.save}, m
|
|
34
|
-
assert_match %r{format\.html \{ redirect_to @post, notice:
|
|
34
|
+
assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully created\." \}}, m
|
|
35
35
|
assert_match %r{format\.json \{ render :show, status: :created, location: @post \}}, m
|
|
36
|
-
assert_match %r{format\.html \{ render :new \}}, m
|
|
36
|
+
assert_match %r{format\.html \{ render :new, status: :unprocessable_entity \}}, m
|
|
37
37
|
assert_match %r{format\.json \{ render json: @post\.errors, status: :unprocessable_entity \}}, m
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
assert_instance_method :update, content do |m|
|
|
41
|
-
assert_match %r{format\.html \{ redirect_to @post, notice:
|
|
41
|
+
assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully updated\." \}}, m
|
|
42
42
|
assert_match %r{format\.json \{ render :show, status: :ok, location: @post \}}, m
|
|
43
|
-
assert_match %r{format\.html \{ render :edit \}}, m
|
|
43
|
+
assert_match %r{format\.html \{ render :edit, status: :unprocessable_entity \}}, m
|
|
44
44
|
assert_match %r{format\.json \{ render json: @post.errors, status: :unprocessable_entity \}}, m
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
assert_instance_method :destroy, content do |m|
|
|
48
48
|
assert_match %r{@post\.destroy}, m
|
|
49
|
-
assert_match %r{format\.html \{ redirect_to posts_url, notice:
|
|
49
|
+
assert_match %r{format\.html \{ redirect_to posts_url, notice: "Post was successfully destroyed\." \}}, m
|
|
50
50
|
assert_match %r{format\.json \{ head :no_content \}}, m
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -67,4 +67,14 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
|
|
|
67
67
|
assert_match %r{params\.fetch\(:post, \{\}\)}, content
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
|
+
|
|
71
|
+
if Rails::VERSION::MAJOR >= 6
|
|
72
|
+
test 'handles virtual attributes' do
|
|
73
|
+
run_generator %w(Message content:rich_text video:attachment photos:attachments)
|
|
74
|
+
|
|
75
|
+
assert_file 'app/controllers/messages_controller.rb' do |content|
|
|
76
|
+
assert_match %r{params\.require\(:message\)\.permit\(:content, :video, photos: \[\]\)}, content
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
70
80
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -3,6 +3,7 @@ require "bundler/setup"
|
|
|
3
3
|
require "active_support"
|
|
4
4
|
require "active_support/core_ext/array/access"
|
|
5
5
|
require "active_support/cache/memory_store"
|
|
6
|
+
require "active_support/json"
|
|
6
7
|
require "active_model"
|
|
7
8
|
require "action_view"
|
|
8
9
|
require "rails/version"
|
|
@@ -10,7 +11,7 @@ require "rails/version"
|
|
|
10
11
|
require "jbuilder"
|
|
11
12
|
|
|
12
13
|
require "active_support/testing/autorun"
|
|
13
|
-
require "mocha/
|
|
14
|
+
require "mocha/minitest"
|
|
14
15
|
|
|
15
16
|
ActiveSupport.test_order = :random
|
|
16
17
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jbuilder
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.11.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 5.0.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 5.0.0
|
|
27
27
|
description:
|
|
28
28
|
email: david@basecamp.com
|
|
29
29
|
executables: []
|
|
@@ -39,10 +39,10 @@ files:
|
|
|
39
39
|
- MIT-LICENSE
|
|
40
40
|
- README.md
|
|
41
41
|
- Rakefile
|
|
42
|
-
- gemfiles/rails_4_2.gemfile
|
|
43
42
|
- gemfiles/rails_5_0.gemfile
|
|
44
43
|
- gemfiles/rails_5_1.gemfile
|
|
45
44
|
- gemfiles/rails_5_2.gemfile
|
|
45
|
+
- gemfiles/rails_6_0.gemfile
|
|
46
46
|
- gemfiles/rails_head.gemfile
|
|
47
47
|
- jbuilder.gemspec
|
|
48
48
|
- lib/generators/rails/jbuilder_generator.rb
|
|
@@ -79,14 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
79
79
|
requirements:
|
|
80
80
|
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
82
|
+
version: 2.2.2
|
|
83
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
84
|
requirements:
|
|
85
85
|
- - ">="
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
87
|
version: '0'
|
|
88
88
|
requirements: []
|
|
89
|
-
rubygems_version: 3.
|
|
89
|
+
rubygems_version: 3.1.2
|
|
90
90
|
signing_key:
|
|
91
91
|
specification_version: 4
|
|
92
92
|
summary: Create JSON structures via a Builder-style DSL
|