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.
@@ -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
- module CollectionRenderable # :nodoc:
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
- def initialize(lookup_context, options, &scope)
71
- super(lookup_context, options)
72
- @scope = scope
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
- def initialize(lookup_context, options, &scope)
86
- super(lookup_context)
87
- @options = options
88
- @scope = scope
89
- end
33
+ private
90
34
 
91
- def render_collection_with_partial(collection, partial, context, block)
92
- render(context, @options.merge(collection: collection, partial: partial), block)
35
+ def build_rendered_template(content, template, layout = nil)
36
+ super(content || json.attributes!, template)
93
37
  end
94
38
 
95
- private
96
- def collection_without_template(view)
97
- @collection = ScopedIterator.new(@collection, @scope)
98
-
99
- super(view)
100
- end
39
+ def build_rendered_collection(templates, _spacer)
40
+ json.merge!(templates.map(&:body))
41
+ end
101
42
 
102
- def collection_with_template(view, template)
103
- @collection = ScopedIterator.new(@collection, @scope)
43
+ def json
44
+ @options[:locals].fetch(:json)
45
+ end
104
46
 
105
- super(view, template)
106
- end
107
- end
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
@@ -1,4 +1,6 @@
1
- require 'jbuilder/jbuilder'
1
+ # frozen_string_literal: true
2
+
3
+ require 'jbuilder/version'
2
4
 
3
5
  class Jbuilder
4
6
  class NullError < ::NoMethodError
@@ -1 +1,3 @@
1
- Jbuilder = Class.new(BasicObject)
1
+ # frozen_string_literal: true
2
+
3
+ require 'jbuilder/version'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Jbuilder::DependencyTracker
2
4
  EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
3
5
 
@@ -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, *args)
15
+ def initialize(context, options = nil)
14
16
  @context = context
15
17
  @cached_root = nil
16
- super(*args)
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 ilustrated below:
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
- _render_explicit_partial(*args)
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 = [], *args)
122
+ def array!(collection = EMPTY_ARRAY, *args, &block)
118
123
  options = args.first
119
124
 
120
- if args.one? && _partial_options?(options)
121
- partial! options.merge(collection: collection)
125
+ if _partial_options?(options)
126
+ options = options.dup
127
+ options[:collection] = collection
128
+ _render_partial_with_options options
122
129
  else
123
- super
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 args.one? && _partial_options?(options)
131
- _set_inline_partial name, object, options
137
+ if _partial_options?(options)
138
+ _set_inline_partial name, object, options.dup
132
139
  else
133
- super
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.reverse_merge! locals: options.except(:partial, :as, :collection, :cached)
141
- options.reverse_merge! ::JbuilderTemplate.template_lookup_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) && CollectionRenderer.supported?
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].merge!(json: self)
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
- if collection.present?
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
- array!
175
+ _array
182
176
  end
183
177
  else
184
- _render_partial options
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{ _render_partial_with_options options.merge(collection: object) }
246
- else
247
- locals = ::Hash[options[:as], object]
248
- _scope{ _render_partial_with_options options.merge(locals: locals) }
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
- # partial! 'name', locals: {foo: 'bar'}
261
- if locals.one? && (locals.keys.first == :locals)
262
- options = locals.merge(partial: name_or_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
- _render_partial_with_options options
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(*args)
7
- @format = {}
8
- @cache = {}
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] ||= @format.inject(key.to_s) do |result, args|
25
- func, args = args
26
- if ::Proc === func
27
- func.call result, *args
28
- else
29
- result.send func, *args
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
@@ -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
- if Rails::VERSION::MAJOR >= 5
13
- module ::ActionController
14
- module ApiRendering
15
- include ActionView::Rendering
16
- end
14
+ module ::ActionController
15
+ module ApiRendering
16
+ include ActionView::Rendering
17
17
  end
18
+ end
18
19
 
19
- ActiveSupport.on_load :action_controller do
20
- if name == 'ActionController::API'
21
- include ActionController::Helpers
22
- include ActionController::ImplicitRender
23
- end
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
- if Rails::VERSION::MAJOR >= 4
29
- generators do |app|
30
- Rails::Generators.configure! app.config.generators
31
- Rails::Generators.hidden_namespaces.uniq!
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
@@ -1,3 +1,5 @@
1
- class Jbuilder
2
- VERSION = "2.13.0"
1
+ # frozen_string_literal: true
2
+
3
+ class Jbuilder < BasicObject
4
+ VERSION = "2.15.1"
3
5
  end