jbuilder 2.12.0 → 2.14.0
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.json +25 -0
- data/.github/workflows/ruby.yml +14 -50
- data/Appraisals +14 -32
- data/CONTRIBUTING.md +1 -7
- data/Gemfile +2 -0
- data/README.md +38 -19
- data/Rakefile +2 -0
- data/bin/release +14 -0
- data/bin/test +6 -0
- data/gemfiles/rails_7_0.gemfile +1 -0
- data/gemfiles/{rails_6_1.gemfile → rails_7_2.gemfile} +1 -1
- data/gemfiles/{rails_6_0.gemfile → rails_8_0.gemfile} +1 -1
- data/jbuilder.gemspec +8 -4
- data/lib/generators/rails/jbuilder_generator.rb +2 -0
- data/lib/generators/rails/scaffold_controller_generator.rb +2 -0
- data/lib/generators/rails/templates/api_controller.rb +6 -0
- data/lib/generators/rails/templates/controller.rb +9 -3
- 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 +36 -50
- data/lib/jbuilder/key_formatter.rb +19 -21
- data/lib/jbuilder/railtie.rb +15 -17
- data/lib/jbuilder/version.rb +5 -0
- data/lib/jbuilder.rb +38 -37
- data/test/jbuilder_generator_test.rb +6 -8
- data/test/jbuilder_template_test.rb +97 -77
- data/test/jbuilder_test.rb +7 -9
- data/test/scaffold_api_controller_generator_test.rb +52 -47
- data/test/scaffold_controller_generator_test.rb +34 -27
- data/test/test_helper.rb +1 -1
- metadata +16 -19
- data/gemfiles/rails_5_0.gemfile +0 -11
- data/gemfiles/rails_5_1.gemfile +0 -11
- data/gemfiles/rails_5_2.gemfile +0 -11
@@ -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
|
@@ -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
|
|
@@ -118,7 +123,9 @@ class JbuilderTemplate < Jbuilder
|
|
118
123
|
options = args.first
|
119
124
|
|
120
125
|
if args.one? && _partial_options?(options)
|
121
|
-
|
126
|
+
options = options.dup
|
127
|
+
options[:collection] = collection
|
128
|
+
_render_partial_with_options options
|
122
129
|
else
|
123
130
|
super
|
124
131
|
end
|
@@ -128,7 +135,7 @@ class JbuilderTemplate < Jbuilder
|
|
128
135
|
options = args.first
|
129
136
|
|
130
137
|
if args.one? && _partial_options?(options)
|
131
|
-
_set_inline_partial name, object, options
|
138
|
+
_set_inline_partial name, object, options.dup
|
132
139
|
else
|
133
140
|
super
|
134
141
|
end
|
@@ -136,15 +143,17 @@ class JbuilderTemplate < Jbuilder
|
|
136
143
|
|
137
144
|
private
|
138
145
|
|
146
|
+
alias_method :method_missing, :set!
|
147
|
+
|
139
148
|
def _render_partial_with_options(options)
|
140
|
-
options
|
141
|
-
options
|
149
|
+
options[:locals] ||= options.except(:partial, :as, :collection, :cached)
|
150
|
+
options[:handlers] ||= ::JbuilderTemplate.template_lookup_options[:handlers]
|
142
151
|
as = options[:as]
|
143
152
|
|
144
|
-
if as && options.key?(:collection)
|
153
|
+
if as && options.key?(:collection)
|
145
154
|
collection = options.delete(:collection) || []
|
146
155
|
partial = options.delete(:partial)
|
147
|
-
options[:locals]
|
156
|
+
options[:locals][:json] = self
|
148
157
|
collection = EnumerableCompat.new(collection) if collection.respond_to?(:count) && !collection.respond_to?(:size)
|
149
158
|
|
150
159
|
if options.has_key?(:layout)
|
@@ -155,21 +164,14 @@ class JbuilderTemplate < Jbuilder
|
|
155
164
|
::Kernel.raise ::NotImplementedError, "The `:spacer_template' option is not supported in collection rendering."
|
156
165
|
end
|
157
166
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
collection = options.delete(:collection)
|
167
|
-
locals = options.delete(:locals)
|
168
|
-
array! collection do |member|
|
169
|
-
member_locals = locals.clone
|
170
|
-
member_locals.merge! collection: collection
|
171
|
-
member_locals.merge! as => member
|
172
|
-
_render_partial options.merge(locals: member_locals)
|
167
|
+
if collection.present?
|
168
|
+
results = CollectionRenderer
|
169
|
+
.new(@context.lookup_context, options) { |&block| _scope(&block) }
|
170
|
+
.render_collection_with_partial(collection, partial, @context, nil)
|
171
|
+
|
172
|
+
array! if results.respond_to?(:body) && results.body.nil?
|
173
|
+
else
|
174
|
+
array!
|
173
175
|
end
|
174
176
|
else
|
175
177
|
_render_partial options
|
@@ -177,7 +179,7 @@ class JbuilderTemplate < Jbuilder
|
|
177
179
|
end
|
178
180
|
|
179
181
|
def _render_partial(options)
|
180
|
-
options[:locals]
|
182
|
+
options[:locals][:json] = self
|
181
183
|
@context.render options
|
182
184
|
end
|
183
185
|
|
@@ -233,34 +235,18 @@ class JbuilderTemplate < Jbuilder
|
|
233
235
|
value = if object.nil?
|
234
236
|
[]
|
235
237
|
elsif _is_collection?(object)
|
236
|
-
_scope
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
end
|
241
|
-
|
242
|
-
set! name, value
|
243
|
-
end
|
244
|
-
|
245
|
-
def _render_explicit_partial(name_or_options, locals = {})
|
246
|
-
case name_or_options
|
247
|
-
when ::Hash
|
248
|
-
# partial! partial: 'name', foo: 'bar'
|
249
|
-
options = name_or_options
|
238
|
+
_scope do
|
239
|
+
options[:collection] = object
|
240
|
+
_render_partial_with_options options
|
241
|
+
end
|
250
242
|
else
|
251
|
-
|
252
|
-
|
253
|
-
options
|
254
|
-
else
|
255
|
-
options = { partial: name_or_options, locals: locals }
|
243
|
+
_scope do
|
244
|
+
options[:locals] = { options[:as] => object }
|
245
|
+
_render_partial_with_options options
|
256
246
|
end
|
257
|
-
# partial! 'name', foo: 'bar'
|
258
|
-
as = locals.delete(:as)
|
259
|
-
options[:as] = as if as.present?
|
260
|
-
options[:collection] = locals[:collection] if locals.key?(:collection)
|
261
247
|
end
|
262
248
|
|
263
|
-
|
249
|
+
_set_value name, value
|
264
250
|
end
|
265
251
|
|
266
252
|
def _render_active_model_partial(object)
|
@@ -275,7 +261,7 @@ class JbuilderHandler
|
|
275
261
|
def self.call(template, source = nil)
|
276
262
|
source ||= template.source
|
277
263
|
# this juggling is required to keep line numbers right in the error
|
278
|
-
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source}
|
264
|
+
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source};
|
279
265
|
json.target! unless (__already_defined && __already_defined != "method")}
|
280
266
|
end
|
281
267
|
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
|
-
@
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
15
|
+
@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.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
require 'jbuilder/jbuilder'
|
3
5
|
require 'jbuilder/blank'
|
@@ -5,24 +7,24 @@ require 'jbuilder/key_formatter'
|
|
5
7
|
require 'jbuilder/errors'
|
6
8
|
require 'json'
|
7
9
|
require 'active_support/core_ext/hash/deep_merge'
|
8
|
-
begin
|
9
|
-
require 'ostruct'
|
10
|
-
rescue LoadError
|
11
|
-
end
|
12
10
|
|
13
11
|
class Jbuilder
|
14
12
|
@@key_formatter = nil
|
15
13
|
@@ignore_nil = false
|
16
14
|
@@deep_format_keys = false
|
17
15
|
|
18
|
-
def initialize(
|
16
|
+
def initialize(
|
17
|
+
key_formatter: @@key_formatter,
|
18
|
+
ignore_nil: @@ignore_nil,
|
19
|
+
deep_format_keys: @@deep_format_keys,
|
20
|
+
&block
|
21
|
+
)
|
19
22
|
@attributes = {}
|
23
|
+
@key_formatter = key_formatter
|
24
|
+
@ignore_nil = ignore_nil
|
25
|
+
@deep_format_keys = deep_format_keys
|
20
26
|
|
21
|
-
|
22
|
-
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
|
23
|
-
@deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys)
|
24
|
-
|
25
|
-
yield self if ::Kernel.block_given?
|
27
|
+
yield self if block
|
26
28
|
end
|
27
29
|
|
28
30
|
# Yields a builder and automatically turns the result into a JSON string
|
@@ -31,7 +33,6 @@ class Jbuilder
|
|
31
33
|
end
|
32
34
|
|
33
35
|
BLANK = Blank.new
|
34
|
-
NON_ENUMERABLES = defined?(::OpenStruct) ? [::Struct, ::OpenStruct].to_set : [::Struct].to_set
|
35
36
|
|
36
37
|
def set!(key, value = BLANK, *args, &block)
|
37
38
|
result = if ::Kernel.block_given?
|
@@ -62,20 +63,12 @@ class Jbuilder
|
|
62
63
|
else
|
63
64
|
# json.author @post.creator, :name, :email_address
|
64
65
|
# { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
|
65
|
-
_merge_block(key){
|
66
|
+
_merge_block(key){ _extract value, args }
|
66
67
|
end
|
67
68
|
|
68
69
|
_set_value key, result
|
69
70
|
end
|
70
71
|
|
71
|
-
def method_missing(*args, &block)
|
72
|
-
if ::Kernel.block_given?
|
73
|
-
set!(*args, &block)
|
74
|
-
else
|
75
|
-
set!(*args)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
72
|
# Specifies formatting to be applied to the key. Passing in a name of a function
|
80
73
|
# will cause that function to be called on the key. So :upcase will upper case
|
81
74
|
# the key. You can also pass in lambdas for more complex transformations.
|
@@ -104,13 +97,13 @@ class Jbuilder
|
|
104
97
|
#
|
105
98
|
# { "_first_name": "David" }
|
106
99
|
#
|
107
|
-
def key_format!(
|
108
|
-
@key_formatter = KeyFormatter.new(
|
100
|
+
def key_format!(...)
|
101
|
+
@key_formatter = KeyFormatter.new(...)
|
109
102
|
end
|
110
103
|
|
111
104
|
# Same as the instance method key_format! except sets the default.
|
112
|
-
def self.key_format(
|
113
|
-
@@key_formatter = KeyFormatter.new(
|
105
|
+
def self.key_format(...)
|
106
|
+
@@key_formatter = KeyFormatter.new(...)
|
114
107
|
end
|
115
108
|
|
116
109
|
# If you want to skip adding nil values to your JSON hash. This is useful
|
@@ -219,7 +212,7 @@ class Jbuilder
|
|
219
212
|
elsif ::Kernel.block_given?
|
220
213
|
_map_collection(collection, &block)
|
221
214
|
elsif attributes.any?
|
222
|
-
_map_collection(collection) { |element|
|
215
|
+
_map_collection(collection) { |element| _extract element, attributes }
|
223
216
|
else
|
224
217
|
_format_keys(collection.to_a)
|
225
218
|
end
|
@@ -245,18 +238,14 @@ class Jbuilder
|
|
245
238
|
#
|
246
239
|
# json.(@person, :name, :age)
|
247
240
|
def extract!(object, *attributes)
|
248
|
-
|
249
|
-
_extract_hash_values(object, attributes)
|
250
|
-
else
|
251
|
-
_extract_method_values(object, attributes)
|
252
|
-
end
|
241
|
+
_extract object, attributes
|
253
242
|
end
|
254
243
|
|
255
244
|
def call(object, *attributes, &block)
|
256
245
|
if ::Kernel.block_given?
|
257
246
|
array! object, &block
|
258
247
|
else
|
259
|
-
|
248
|
+
_extract object, attributes
|
260
249
|
end
|
261
250
|
end
|
262
251
|
|
@@ -285,6 +274,16 @@ class Jbuilder
|
|
285
274
|
|
286
275
|
private
|
287
276
|
|
277
|
+
alias_method :method_missing, :set!
|
278
|
+
|
279
|
+
def _extract(object, attributes)
|
280
|
+
if ::Hash === object
|
281
|
+
_extract_hash_values(object, attributes)
|
282
|
+
else
|
283
|
+
_extract_method_values(object, attributes)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
288
287
|
def _extract_hash_values(object, attributes)
|
289
288
|
attributes.each{ |key| _set_value key, _format_keys(object.fetch(key)) }
|
290
289
|
end
|
@@ -315,7 +314,13 @@ class Jbuilder
|
|
315
314
|
end
|
316
315
|
|
317
316
|
def _key(key)
|
318
|
-
|
317
|
+
if @key_formatter
|
318
|
+
@key_formatter.format(key)
|
319
|
+
elsif key.is_a?(::Symbol)
|
320
|
+
key.name
|
321
|
+
else
|
322
|
+
key.to_s
|
323
|
+
end
|
319
324
|
end
|
320
325
|
|
321
326
|
def _format_keys(hash_or_array)
|
@@ -354,16 +359,12 @@ class Jbuilder
|
|
354
359
|
end
|
355
360
|
|
356
361
|
def _is_collection?(object)
|
357
|
-
|
362
|
+
object.respond_to?(:map) && object.respond_to?(:count) && !(::Struct === object)
|
358
363
|
end
|
359
364
|
|
360
365
|
def _blank?(value=@attributes)
|
361
366
|
BLANK == value
|
362
367
|
end
|
363
|
-
|
364
|
-
def _object_respond_to?(object, *methods)
|
365
|
-
methods.all?{ |m| object.respond_to?(m) }
|
366
|
-
end
|
367
368
|
end
|
368
369
|
|
369
370
|
require 'jbuilder/railtie' if defined?(Rails)
|
@@ -56,15 +56,13 @@ class JbuilderGeneratorTest < Rails::Generators::TestCase
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
run_generator %w(Message content:rich_text video:attachment photos:attachments)
|
59
|
+
test 'handles virtual attributes' do
|
60
|
+
run_generator %w(Message content:rich_text video:attachment photos:attachments)
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
62
|
+
assert_file 'app/views/messages/_message.json.jbuilder' do |content|
|
63
|
+
assert_match %r{json\.content message\.content\.to_s}, content
|
64
|
+
assert_match %r{json\.video url_for\(message\.video\)}, content
|
65
|
+
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
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|