jbuilder 2.9.1 → 2.11.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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +14 -29
- data/Appraisals +8 -14
- data/CHANGELOG.md +29 -0
- data/CONTRIBUTING.md +1 -3
- data/gemfiles/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 +28 -16
- data/lib/jbuilder/jbuilder_template.rb +3 -3
- data/test/jbuilder_generator_test.rb +12 -0
- data/test/jbuilder_test.rb +84 -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 +1 -1
- metadata +6 -7
- data/gemfiles/rails_4_2.gemfile +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3e3eebf3fe3849616361ae7df9556f466eaf84da813756b8690dfbd5c28d41a1
|
|
4
|
+
data.tar.gz: 011c0162b09a94f229673e88bab0d0d466d9552a004afb426f817a02c3af8943
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 29968e2f35da52dc00db229d0085d77a7d390417bbe3011b005824ff45a1291bca0f45c59d4f40263a3ac236e31ea3fdd0cd78ba01ddef4e51414aea4ac34704
|
|
7
|
+
data.tar.gz: '09df7fb01ce2d128b0f45116cc4f2ccb01469031a51b598f6c17c16f58ddbd0c3059095a1a6761a2f26e328b3960def55752d6ed36cca0e2952e393d712e48b3'
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -3,20 +3,18 @@ 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
|
|
@@ -24,41 +22,28 @@ gemfile:
|
|
|
24
22
|
- gemfiles/rails_head.gemfile
|
|
25
23
|
|
|
26
24
|
matrix:
|
|
27
|
-
include:
|
|
28
|
-
- rvm: 1.9
|
|
29
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
30
|
-
- rvm: 2.0
|
|
31
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
32
|
-
- rvm: 2.1
|
|
33
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
34
|
-
- rvm: 2.3
|
|
35
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
36
|
-
- rvm: jruby-19mode
|
|
37
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
38
|
-
- rvm: rbx-3.107
|
|
39
|
-
gemfile: gemfiles/rails_4_2.gemfile
|
|
40
25
|
exclude:
|
|
41
|
-
- rvm: 2.
|
|
42
|
-
gemfile: gemfiles/
|
|
43
|
-
- rvm: 2.
|
|
44
|
-
gemfile: gemfiles/
|
|
45
|
-
- rvm: 2.
|
|
46
|
-
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
|
|
47
34
|
- rvm: 2.2.10
|
|
48
35
|
gemfile: gemfiles/rails_6_0.gemfile
|
|
49
36
|
- rvm: 2.3.8
|
|
50
37
|
gemfile: gemfiles/rails_6_0.gemfile
|
|
51
|
-
- rvm: 2.4.
|
|
38
|
+
- rvm: 2.4.10
|
|
52
39
|
gemfile: gemfiles/rails_6_0.gemfile
|
|
53
40
|
- rvm: 2.2.10
|
|
54
41
|
gemfile: gemfiles/rails_head.gemfile
|
|
55
42
|
- rvm: 2.3.8
|
|
56
43
|
gemfile: gemfiles/rails_head.gemfile
|
|
57
|
-
- rvm: 2.4.
|
|
44
|
+
- rvm: 2.4.10
|
|
58
45
|
gemfile: gemfiles/rails_head.gemfile
|
|
59
46
|
allow_failures:
|
|
60
|
-
- rvm: jruby-19mode
|
|
61
|
-
- rvm: rbx-3.107
|
|
62
47
|
- rvm: ruby-head
|
|
63
48
|
- gemfile: gemfiles/rails_head.gemfile
|
|
64
49
|
fast_finish: true
|
data/Appraisals
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
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"
|
|
20
14
|
appraise "rails-6-0" do
|
|
21
|
-
gem "rails", "~> 6.0.0
|
|
15
|
+
gem "rails", "~> 6.0.0"
|
|
22
16
|
end
|
|
23
17
|
|
|
24
18
|
appraise "rails-head" do
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
2.11.1
|
|
4
|
+
------
|
|
5
|
+
|
|
6
|
+
* Use symbols instead of strings for before_action fitlers [DHH]
|
|
7
|
+
* Slim down comments in generated scaffold code [DHH]
|
|
8
|
+
|
|
9
|
+
2.11.0
|
|
10
|
+
------
|
|
11
|
+
|
|
12
|
+
* [Allow jbuilder instance to be passed to #merge!](https://github.com/rails/jbuilder/pull/485)
|
|
13
|
+
* [Fix for key_format! when using nested hashes](https://github.com/rails/jbuilder/pull/486)
|
|
14
|
+
* [Include rich_text, attachment, and attachments fields in json partial](https://github.com/rails/jbuilder/pull/459)
|
|
15
|
+
|
|
16
|
+
2.10.2
|
|
17
|
+
------
|
|
18
|
+
|
|
19
|
+
* Update scaffold generator to use double quotes, 422 form error responds, and modern string-of-arrays syntax [DHH]
|
|
20
|
+
|
|
21
|
+
2.10.1
|
|
22
|
+
------
|
|
23
|
+
|
|
24
|
+
* Fix keyword arguments warning on Ruby 2.7
|
|
25
|
+
|
|
26
|
+
2.10.0
|
|
27
|
+
------
|
|
28
|
+
|
|
29
|
+
* Requires Rails 5+ and Ruby 2.2+
|
|
30
|
+
* Nested hashes are deep-merged
|
|
31
|
+
|
|
3
32
|
2.9.1
|
|
4
33
|
-----
|
|
5
34
|
|
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/gemfiles/rails_6_0.gemfile
CHANGED
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.1'
|
|
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,6 +4,7 @@ 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
|
|
@@ -26,12 +27,12 @@ class Jbuilder
|
|
|
26
27
|
BLANK = Blank.new
|
|
27
28
|
NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set
|
|
28
29
|
|
|
29
|
-
def set!(key, value = BLANK, *args)
|
|
30
|
+
def set!(key, value = BLANK, *args, &block)
|
|
30
31
|
result = if ::Kernel.block_given?
|
|
31
32
|
if !_blank?(value)
|
|
32
33
|
# json.comments @post.comments { |comment| ... }
|
|
33
34
|
# { "comments": [ { ... }, { ... } ] }
|
|
34
|
-
_scope{ array! value,
|
|
35
|
+
_scope{ array! value, &block }
|
|
35
36
|
else
|
|
36
37
|
# json.comments { ... }
|
|
37
38
|
# { "comments": ... }
|
|
@@ -42,11 +43,11 @@ class Jbuilder
|
|
|
42
43
|
# json.age 32
|
|
43
44
|
# json.person another_jbuilder
|
|
44
45
|
# { "age": 32, "person": { ... }
|
|
45
|
-
value.attributes!
|
|
46
|
+
_format_keys(value.attributes!)
|
|
46
47
|
else
|
|
47
48
|
# json.age 32
|
|
48
49
|
# { "age": 32 }
|
|
49
|
-
value
|
|
50
|
+
_format_keys(value)
|
|
50
51
|
end
|
|
51
52
|
elsif _is_collection?(value)
|
|
52
53
|
# json.comments @post.comments, :content, :created_at
|
|
@@ -61,9 +62,9 @@ class Jbuilder
|
|
|
61
62
|
_set_value key, result
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
def method_missing(*args)
|
|
65
|
+
def method_missing(*args, &block)
|
|
65
66
|
if ::Kernel.block_given?
|
|
66
|
-
set!(*args,
|
|
67
|
+
set!(*args, &block)
|
|
67
68
|
else
|
|
68
69
|
set!(*args)
|
|
69
70
|
end
|
|
@@ -163,7 +164,7 @@ class Jbuilder
|
|
|
163
164
|
#
|
|
164
165
|
# [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ]
|
|
165
166
|
#
|
|
166
|
-
#
|
|
167
|
+
# You can use the call syntax instead of an explicit extract! call:
|
|
167
168
|
#
|
|
168
169
|
# json.(@people) { |person| ... }
|
|
169
170
|
#
|
|
@@ -181,11 +182,11 @@ class Jbuilder
|
|
|
181
182
|
# json.array! [1, 2, 3]
|
|
182
183
|
#
|
|
183
184
|
# [1,2,3]
|
|
184
|
-
def array!(collection = [], *attributes)
|
|
185
|
+
def array!(collection = [], *attributes, &block)
|
|
185
186
|
array = if collection.nil?
|
|
186
187
|
[]
|
|
187
188
|
elsif ::Kernel.block_given?
|
|
188
|
-
_map_collection(collection,
|
|
189
|
+
_map_collection(collection, &block)
|
|
189
190
|
elsif attributes.any?
|
|
190
191
|
_map_collection(collection) { |element| extract! element, *attributes }
|
|
191
192
|
else
|
|
@@ -220,9 +221,9 @@ class Jbuilder
|
|
|
220
221
|
end
|
|
221
222
|
end
|
|
222
223
|
|
|
223
|
-
def call(object, *attributes)
|
|
224
|
+
def call(object, *attributes, &block)
|
|
224
225
|
if ::Kernel.block_given?
|
|
225
|
-
array! object,
|
|
226
|
+
array! object, &block
|
|
226
227
|
else
|
|
227
228
|
extract! object, *attributes
|
|
228
229
|
end
|
|
@@ -240,8 +241,9 @@ class Jbuilder
|
|
|
240
241
|
@attributes
|
|
241
242
|
end
|
|
242
243
|
|
|
243
|
-
# Merges hash or
|
|
244
|
-
def merge!(
|
|
244
|
+
# Merges hash, array, or Jbuilder instance into current builder.
|
|
245
|
+
def merge!(object)
|
|
246
|
+
hash_or_array = ::Jbuilder === object ? object.attributes! : object
|
|
245
247
|
@attributes = _merge_values(@attributes, hash_or_array)
|
|
246
248
|
end
|
|
247
249
|
|
|
@@ -271,11 +273,11 @@ class Jbuilder
|
|
|
271
273
|
if _blank?(updates)
|
|
272
274
|
current_value
|
|
273
275
|
elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
|
|
274
|
-
updates
|
|
276
|
+
_format_keys(updates)
|
|
275
277
|
elsif ::Array === current_value && ::Array === updates
|
|
276
|
-
current_value + updates
|
|
278
|
+
current_value + _format_keys(updates)
|
|
277
279
|
elsif ::Hash === current_value && ::Hash === updates
|
|
278
|
-
current_value.
|
|
280
|
+
current_value.deep_merge(_format_keys(updates))
|
|
279
281
|
else
|
|
280
282
|
raise MergeError.build(current_value, updates)
|
|
281
283
|
end
|
|
@@ -285,6 +287,16 @@ class Jbuilder
|
|
|
285
287
|
@key_formatter ? @key_formatter.format(key) : key.to_s
|
|
286
288
|
end
|
|
287
289
|
|
|
290
|
+
def _format_keys(hash_or_array)
|
|
291
|
+
if ::Array === hash_or_array
|
|
292
|
+
hash_or_array.map { |value| _format_keys(value) }
|
|
293
|
+
elsif ::Hash === hash_or_array
|
|
294
|
+
::Hash[hash_or_array.collect { |k, v| [_key(k), _format_keys(v)] }]
|
|
295
|
+
else
|
|
296
|
+
hash_or_array
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
288
300
|
def _set_value(key, value)
|
|
289
301
|
raise NullError.build(key) if @attributes.nil?
|
|
290
302
|
raise ArrayError.build(key) if ::Array === @attributes
|
|
@@ -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
|
|
|
@@ -562,6 +593,58 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
|
562
593
|
assert_equal ['oats and friends'], result.keys
|
|
563
594
|
end
|
|
564
595
|
|
|
596
|
+
test 'key_format! with merge!' do
|
|
597
|
+
hash = { camel_style: 'for JS' }
|
|
598
|
+
result = jbuild do |json|
|
|
599
|
+
json.key_format! camelize: :lower
|
|
600
|
+
json.merge! hash
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
assert_equal ['camelStyle'], result.keys
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
test 'key_format! with merge! deep' do
|
|
607
|
+
hash = { camel_style: { sub_attr: 'for JS' } }
|
|
608
|
+
result = jbuild do |json|
|
|
609
|
+
json.key_format! camelize: :lower
|
|
610
|
+
json.merge! hash
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
assert_equal ['subAttr'], result['camelStyle'].keys
|
|
614
|
+
end
|
|
615
|
+
|
|
616
|
+
test 'key_format! with set! array of hashes' do
|
|
617
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
618
|
+
result = jbuild do |json|
|
|
619
|
+
json.key_format! camelize: :lower
|
|
620
|
+
json.set! :names, names
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
assert_equal %w[firstName lastName], result['names'][0].keys
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
test 'key_format! with array! of hashes' do
|
|
627
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
628
|
+
result = jbuild do |json|
|
|
629
|
+
json.key_format! camelize: :lower
|
|
630
|
+
json.array! names
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
assert_equal %w[firstName lastName], result[0].keys
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
test 'key_format! with merge! array of hashes' do
|
|
637
|
+
names = [{ first_name: 'camel', last_name: 'case' }]
|
|
638
|
+
new_names = [{ first_name: 'snake', last_name: 'case' }]
|
|
639
|
+
result = jbuild do |json|
|
|
640
|
+
json.key_format! camelize: :lower
|
|
641
|
+
json.array! names
|
|
642
|
+
json.merge! new_names
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
assert_equal %w[firstName lastName], result[1].keys
|
|
646
|
+
end
|
|
647
|
+
|
|
565
648
|
test 'default key_format!' do
|
|
566
649
|
Jbuilder.key_format camelize: :lower
|
|
567
650
|
result = jbuild{ |json| json.camel_style 'for JS' }
|
|
@@ -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
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.1
|
|
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-24 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,7 +39,6 @@ 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
|
|
@@ -80,14 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
80
79
|
requirements:
|
|
81
80
|
- - ">="
|
|
82
81
|
- !ruby/object:Gem::Version
|
|
83
|
-
version:
|
|
82
|
+
version: 2.2.2
|
|
84
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
84
|
requirements:
|
|
86
85
|
- - ">="
|
|
87
86
|
- !ruby/object:Gem::Version
|
|
88
87
|
version: '0'
|
|
89
88
|
requirements: []
|
|
90
|
-
rubygems_version: 3.
|
|
89
|
+
rubygems_version: 3.1.2
|
|
91
90
|
signing_key:
|
|
92
91
|
specification_version: 4
|
|
93
92
|
summary: Create JSON structures via a Builder-style DSL
|