Skip to content

Commit fddb7ca

Browse files
committed
Optimize array! DSL
1 parent 38339ad commit fddb7ca

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

lib/jbuilder.rb

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
require 'jbuilder/errors'
88
require 'json'
99
require 'active_support/core_ext/hash/deep_merge'
10+
require 'active_support/core_ext/object/blank'
1011

1112
class Jbuilder
1213
@@key_formatter = nil
@@ -32,14 +33,16 @@ def self.encode(...)
3233
new(...).target!
3334
end
3435

35-
BLANK = Blank.new
36+
BLANK = Blank.new.freeze
37+
EMPTY_ARRAY = [].freeze
38+
private_constant :BLANK, :EMPTY_ARRAY
3639

3740
def set!(key, value = BLANK, *args, &block)
3841
result = if ::Kernel.block_given?
3942
if !_blank?(value)
4043
# json.comments @post.comments { |comment| ... }
4144
# { "comments": [ { ... }, { ... } ] }
42-
_scope{ array! value, &block }
45+
_scope{ _array value, &block }
4346
else
4447
# json.comments { ... }
4548
# { "comments": ... }
@@ -59,7 +62,7 @@ def set!(key, value = BLANK, *args, &block)
5962
elsif _is_collection?(value)
6063
# json.comments @post.comments, :content, :created_at
6164
# { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
62-
_scope{ array! value, *args }
65+
_scope{ _array value, args }
6366
else
6467
# json.author @post.creator, :name, :email_address
6568
# { "author": { "name": "David", "email_address": "[email protected]" } }
@@ -206,18 +209,8 @@ def child!
206209
# json.array! [1, 2, 3]
207210
#
208211
# [1,2,3]
209-
def array!(collection = [], *attributes, &block)
210-
array = if collection.nil?
211-
[]
212-
elsif ::Kernel.block_given?
213-
_map_collection(collection, &block)
214-
elsif attributes.any?
215-
_map_collection(collection) { |element| _extract element, attributes }
216-
else
217-
_format_keys(collection.to_a)
218-
end
219-
220-
@attributes = _merge_values(@attributes, array)
212+
def array!(collection = EMPTY_ARRAY, *attributes, &block)
213+
_array collection, attributes, &block
221214
end
222215

223216
# Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
@@ -243,7 +236,7 @@ def extract!(object, *attributes)
243236

244237
def call(object, *attributes, &block)
245238
if ::Kernel.block_given?
246-
array! object, &block
239+
_array object, &block
247240
else
248241
_extract object, attributes
249242
end
@@ -276,6 +269,20 @@ def target!
276269

277270
alias_method :method_missing, :set!
278271

272+
def _array(collection = EMPTY_ARRAY, attributes = nil, &block)
273+
array = if collection.nil?
274+
EMPTY_ARRAY
275+
elsif block
276+
_map_collection(collection, &block)
277+
elsif attributes.present?
278+
_map_collection(collection) { |element| _extract element, attributes }
279+
else
280+
_format_keys(collection.to_a)
281+
end
282+
283+
@attributes = _merge_values(@attributes, array)
284+
end
285+
279286
def _extract(object, attributes)
280287
if ::Hash === object
281288
_extract_hash_values(object, attributes)

lib/jbuilder/jbuilder_template.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@ def target!
119119
@cached_root || super
120120
end
121121

122-
def array!(collection = [], *args)
122+
def array!(collection = EMPTY_ARRAY, *args, &block)
123123
options = args.first
124124

125-
if args.one? && _partial_options?(options)
125+
if _partial_options?(options)
126126
options = options.dup
127127
options[:collection] = collection
128128
_render_partial_with_options options
129129
else
130-
super
130+
_array collection, args, &block
131131
end
132132
end
133133

@@ -151,7 +151,7 @@ def _render_partial_with_options(options)
151151
as = options[:as]
152152

153153
if as && options.key?(:collection)
154-
collection = options.delete(:collection) || []
154+
collection = options.delete(:collection) || EMPTY_ARRAY
155155
partial = options.delete(:partial)
156156
options[:locals][:json] = self
157157
collection = EnumerableCompat.new(collection) if collection.respond_to?(:count) && !collection.respond_to?(:size)
@@ -169,9 +169,9 @@ def _render_partial_with_options(options)
169169
.new(@context.lookup_context, options) { |&block| _scope(&block) }
170170
.render_collection_with_partial(collection, partial, @context, nil)
171171

172-
array! if results.respond_to?(:body) && results.body.nil?
172+
_array if results.respond_to?(:body) && results.body.nil?
173173
else
174-
array!
174+
_array
175175
end
176176
else
177177
_render_partial options
@@ -233,7 +233,7 @@ def _is_active_model?(object)
233233

234234
def _set_inline_partial(name, object, options)
235235
value = if object.nil?
236-
[]
236+
EMPTY_ARRAY
237237
elsif _is_collection?(object)
238238
_scope do
239239
options[:collection] = object

0 commit comments

Comments
 (0)