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 +4 -4
- data/.devcontainer/devcontainer-lock.json +9 -0
- data/.devcontainer/devcontainer.json +25 -0
- data/.github/workflows/ruby.yml +23 -6
- data/Appraisals +25 -12
- data/Gemfile +2 -0
- data/README.md +63 -22
- 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/gemfiles/rails_8_1.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 +6 -0
- data/lib/generators/rails/templates/api_controller.rb +2 -2
- data/lib/generators/rails/templates/controller.rb +6 -6
- 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 +41 -67
- 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 +101 -82
- data/test/jbuilder_generator_test.rb +6 -8
- data/test/jbuilder_template_test.rb +116 -80
- data/test/jbuilder_test.rb +21 -8
- data/test/scaffold_api_controller_generator_test.rb +56 -56
- data/test/scaffold_controller_generator_test.rb +37 -33
- data/test/test_helper.rb +2 -2
- metadata +15 -14
|
@@ -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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'jbuilder/jbuilder'
|
|
2
4
|
require 'jbuilder/collection_renderer'
|
|
3
5
|
require 'action_dispatch/http/mime_type'
|
|
@@ -10,10 +12,11 @@ class JbuilderTemplate < Jbuilder
|
|
|
10
12
|
|
|
11
13
|
self.template_lookup_options = { handlers: [:jbuilder] }
|
|
12
14
|
|
|
13
|
-
def initialize(context,
|
|
15
|
+
def initialize(context, options = nil)
|
|
14
16
|
@context = context
|
|
15
17
|
@cached_root = nil
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
options.nil? ? super() : super(**options)
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
# Generates JSON using the template specified with the `:partial` option. For example, the code below will render
|
|
@@ -24,7 +27,7 @@ class JbuilderTemplate < Jbuilder
|
|
|
24
27
|
#
|
|
25
28
|
# json.partial! 'comments/comments', comments: @message.comments
|
|
26
29
|
#
|
|
27
|
-
# There are multiple ways to generate a collection of elements as JSON, as
|
|
30
|
+
# There are multiple ways to generate a collection of elements as JSON, as illustrated below:
|
|
28
31
|
#
|
|
29
32
|
# Example:
|
|
30
33
|
#
|
|
@@ -52,7 +55,9 @@ class JbuilderTemplate < Jbuilder
|
|
|
52
55
|
if args.one? && _is_active_model?(args.first)
|
|
53
56
|
_render_active_model_partial args.first
|
|
54
57
|
else
|
|
55
|
-
|
|
58
|
+
options = args.extract_options!.dup
|
|
59
|
+
options[:partial] = args.first if args.present?
|
|
60
|
+
_render_partial_with_options options
|
|
56
61
|
end
|
|
57
62
|
end
|
|
58
63
|
|
|
@@ -114,37 +119,42 @@ class JbuilderTemplate < Jbuilder
|
|
|
114
119
|
@cached_root || super
|
|
115
120
|
end
|
|
116
121
|
|
|
117
|
-
def array!(collection =
|
|
122
|
+
def array!(collection = EMPTY_ARRAY, *args, &block)
|
|
118
123
|
options = args.first
|
|
119
124
|
|
|
120
|
-
if
|
|
121
|
-
|
|
125
|
+
if _partial_options?(options)
|
|
126
|
+
options = options.dup
|
|
127
|
+
options[:collection] = collection
|
|
128
|
+
_render_partial_with_options options
|
|
122
129
|
else
|
|
123
|
-
|
|
130
|
+
_array collection, args, &block
|
|
124
131
|
end
|
|
125
132
|
end
|
|
126
133
|
|
|
127
|
-
def set!(name, object = BLANK, *args)
|
|
134
|
+
def set!(name, object = BLANK, *args, &block)
|
|
128
135
|
options = args.first
|
|
129
136
|
|
|
130
|
-
if
|
|
131
|
-
_set_inline_partial name, object, options
|
|
137
|
+
if _partial_options?(options)
|
|
138
|
+
_set_inline_partial name, object, options.dup
|
|
132
139
|
else
|
|
133
|
-
|
|
140
|
+
_set name, object, args, &block
|
|
134
141
|
end
|
|
135
142
|
end
|
|
136
143
|
|
|
144
|
+
alias_method :method_missing, :set!
|
|
145
|
+
private :method_missing
|
|
146
|
+
|
|
137
147
|
private
|
|
138
148
|
|
|
139
149
|
def _render_partial_with_options(options)
|
|
140
|
-
options
|
|
141
|
-
options
|
|
150
|
+
options[:locals] ||= options.except(:partial, :as, :collection, :cached)
|
|
151
|
+
options[:handlers] ||= ::JbuilderTemplate.template_lookup_options[:handlers]
|
|
142
152
|
as = options[:as]
|
|
143
153
|
|
|
144
|
-
if as && options.key?(:collection)
|
|
145
|
-
collection = options.delete(:collection) ||
|
|
154
|
+
if as && options.key?(:collection)
|
|
155
|
+
collection = options.delete(:collection) || EMPTY_ARRAY
|
|
146
156
|
partial = options.delete(:partial)
|
|
147
|
-
options[:locals]
|
|
157
|
+
options[:locals][:json] = self
|
|
148
158
|
collection = EnumerableCompat.new(collection) if collection.respond_to?(:count) && !collection.respond_to?(:size)
|
|
149
159
|
|
|
150
160
|
if options.has_key?(:layout)
|
|
@@ -159,37 +169,17 @@ class JbuilderTemplate < Jbuilder
|
|
|
159
169
|
results = CollectionRenderer
|
|
160
170
|
.new(@context.lookup_context, options) { |&block| _scope(&block) }
|
|
161
171
|
.render_collection_with_partial(collection, partial, @context, nil)
|
|
162
|
-
|
|
163
|
-
array! if results.respond_to?(:body) && results.body.nil?
|
|
164
|
-
else
|
|
165
|
-
array!
|
|
166
|
-
end
|
|
167
|
-
elsif as && options.key?(:collection) && !CollectionRenderer.supported?
|
|
168
|
-
# For Rails <= 5.2:
|
|
169
|
-
as = as.to_sym
|
|
170
|
-
collection = options.delete(:collection)
|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
locals = options.delete(:locals)
|
|
174
|
-
array! collection do |member|
|
|
175
|
-
member_locals = locals.clone
|
|
176
|
-
member_locals.merge! collection: collection
|
|
177
|
-
member_locals.merge! as => member
|
|
178
|
-
_render_partial options.merge(locals: member_locals)
|
|
179
|
-
end
|
|
173
|
+
_array if results.respond_to?(:body) && results.body.nil?
|
|
180
174
|
else
|
|
181
|
-
|
|
175
|
+
_array
|
|
182
176
|
end
|
|
183
177
|
else
|
|
184
|
-
|
|
178
|
+
options[:locals][:json] = self
|
|
179
|
+
@context.render options
|
|
185
180
|
end
|
|
186
181
|
end
|
|
187
182
|
|
|
188
|
-
def _render_partial(options)
|
|
189
|
-
options[:locals].merge! json: self
|
|
190
|
-
@context.render options
|
|
191
|
-
end
|
|
192
|
-
|
|
193
183
|
def _cache_fragment_for(key, options, &block)
|
|
194
184
|
key = _cache_key(key, options)
|
|
195
185
|
_read_fragment_cache(key, options) || _write_fragment_cache(key, options, &block)
|
|
@@ -240,36 +230,20 @@ class JbuilderTemplate < Jbuilder
|
|
|
240
230
|
|
|
241
231
|
def _set_inline_partial(name, object, options)
|
|
242
232
|
value = if object.nil?
|
|
243
|
-
|
|
233
|
+
EMPTY_ARRAY
|
|
244
234
|
elsif _is_collection?(object)
|
|
245
|
-
_scope
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
set! name, value
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def _render_explicit_partial(name_or_options, locals = {})
|
|
255
|
-
case name_or_options
|
|
256
|
-
when ::Hash
|
|
257
|
-
# partial! partial: 'name', foo: 'bar'
|
|
258
|
-
options = name_or_options
|
|
235
|
+
_scope do
|
|
236
|
+
options[:collection] = object
|
|
237
|
+
_render_partial_with_options options
|
|
238
|
+
end
|
|
259
239
|
else
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
options
|
|
263
|
-
else
|
|
264
|
-
options = { partial: name_or_options, locals: locals }
|
|
240
|
+
_scope do
|
|
241
|
+
options[options[:as]] = object
|
|
242
|
+
_render_partial_with_options options
|
|
265
243
|
end
|
|
266
|
-
# partial! 'name', foo: 'bar'
|
|
267
|
-
as = locals.delete(:as)
|
|
268
|
-
options[:as] = as if as.present?
|
|
269
|
-
options[:collection] = locals[:collection] if locals.key?(:collection)
|
|
270
244
|
end
|
|
271
245
|
|
|
272
|
-
|
|
246
|
+
_set_value name, value
|
|
273
247
|
end
|
|
274
248
|
|
|
275
249
|
def _render_active_model_partial(object)
|
|
@@ -284,7 +258,7 @@ class JbuilderHandler
|
|
|
284
258
|
def self.call(template, source = nil)
|
|
285
259
|
source ||= template.source
|
|
286
260
|
# this juggling is required to keep line numbers right in the error
|
|
287
|
-
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source}
|
|
261
|
+
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source};
|
|
288
262
|
json.target! unless (__already_defined && __already_defined != "method")}
|
|
289
263
|
end
|
|
290
264
|
end
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'jbuilder/jbuilder'
|
|
2
|
-
require 'active_support/core_ext/array'
|
|
3
4
|
|
|
4
5
|
class Jbuilder
|
|
5
6
|
class KeyFormatter
|
|
6
|
-
def initialize(*
|
|
7
|
-
@
|
|
8
|
-
@
|
|
9
|
-
|
|
10
|
-
options = args.extract_options!
|
|
11
|
-
args.each do |name|
|
|
12
|
-
@format[name] = []
|
|
13
|
-
end
|
|
14
|
-
options.each do |name, parameters|
|
|
15
|
-
@format[name] = parameters
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def initialize_copy(original)
|
|
7
|
+
def initialize(*formats, **formats_with_options)
|
|
8
|
+
@mutex = Mutex.new
|
|
9
|
+
@formats = formats
|
|
10
|
+
@formats_with_options = formats_with_options
|
|
20
11
|
@cache = {}
|
|
21
12
|
end
|
|
22
13
|
|
|
23
14
|
def format(key)
|
|
24
|
-
@cache[key]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
@cache[key] || @mutex.synchronize do
|
|
16
|
+
@cache[key] ||= begin
|
|
17
|
+
value = key.is_a?(Symbol) ? key.name : key.to_s
|
|
18
|
+
|
|
19
|
+
@formats.each do |func|
|
|
20
|
+
value = func.is_a?(Proc) ? func.call(value) : value.send(func)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@formats_with_options.each do |func, params|
|
|
24
|
+
value = func.is_a?(Proc) ? func.call(value, *params) : value.send(func, *params)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
value
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
end
|
data/lib/jbuilder/railtie.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rails'
|
|
2
4
|
require 'jbuilder/jbuilder_template'
|
|
3
5
|
|
|
@@ -9,28 +11,24 @@ class Jbuilder
|
|
|
9
11
|
require 'jbuilder/jbuilder_dependency_tracker'
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
module
|
|
14
|
-
|
|
15
|
-
include ActionView::Rendering
|
|
16
|
-
end
|
|
14
|
+
module ::ActionController
|
|
15
|
+
module ApiRendering
|
|
16
|
+
include ActionView::Rendering
|
|
17
17
|
end
|
|
18
|
+
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
end
|
|
20
|
+
ActiveSupport.on_load :action_controller_api do
|
|
21
|
+
include ActionController::Helpers
|
|
22
|
+
include ActionController::ImplicitRender
|
|
23
|
+
helper_method :combined_fragment_cache_key
|
|
24
|
+
helper_method :view_cache_dependencies
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
require 'generators/rails/scaffold_controller_generator'
|
|
33
|
-
end
|
|
28
|
+
generators do |app|
|
|
29
|
+
Rails::Generators.configure! app.config.generators
|
|
30
|
+
Rails::Generators.hidden_namespaces.uniq!
|
|
31
|
+
require 'generators/rails/scaffold_controller_generator'
|
|
34
32
|
end
|
|
35
33
|
end
|
|
36
34
|
end
|
data/lib/jbuilder/version.rb
CHANGED