jbuilder 2.10.0 → 2.14.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +25 -0
  3. data/.github/workflows/ruby.yml +56 -0
  4. data/.gitignore +2 -0
  5. data/Appraisals +14 -13
  6. data/CONTRIBUTING.md +5 -13
  7. data/Gemfile +2 -0
  8. data/README.md +113 -26
  9. data/Rakefile +3 -1
  10. data/bin/release +14 -0
  11. data/bin/test +6 -0
  12. data/gemfiles/{rails_5_1.gemfile → rails_7_0.gemfile} +2 -1
  13. data/gemfiles/{rails_5_2.gemfile → rails_7_1.gemfile} +1 -1
  14. data/gemfiles/{rails_6_0.gemfile → rails_7_2.gemfile} +1 -1
  15. data/gemfiles/{rails_5_0.gemfile → rails_8_0.gemfile} +1 -1
  16. data/gemfiles/rails_head.gemfile +1 -1
  17. data/jbuilder.gemspec +22 -3
  18. data/lib/generators/rails/jbuilder_generator.rb +10 -0
  19. data/lib/generators/rails/scaffold_controller_generator.rb +2 -0
  20. data/lib/generators/rails/templates/api_controller.rb +8 -2
  21. data/lib/generators/rails/templates/controller.rb +19 -17
  22. data/lib/generators/rails/templates/index.json.jbuilder +1 -1
  23. data/lib/generators/rails/templates/partial.json.jbuilder +14 -0
  24. data/lib/generators/rails/templates/show.json.jbuilder +1 -1
  25. data/lib/jbuilder/blank.rb +2 -0
  26. data/lib/jbuilder/collection_renderer.rb +58 -0
  27. data/lib/jbuilder/errors.rb +3 -1
  28. data/lib/jbuilder/jbuilder.rb +3 -7
  29. data/lib/jbuilder/jbuilder_dependency_tracker.rb +75 -0
  30. data/lib/jbuilder/jbuilder_template.rb +82 -48
  31. data/lib/jbuilder/key_formatter.rb +19 -21
  32. data/lib/jbuilder/railtie.rb +17 -19
  33. data/lib/jbuilder/version.rb +5 -0
  34. data/lib/jbuilder.rb +96 -51
  35. data/test/jbuilder_dependency_tracker_test.rb +2 -3
  36. data/test/jbuilder_generator_test.rb +22 -0
  37. data/test/jbuilder_template_test.rb +133 -8
  38. data/test/jbuilder_test.rb +211 -9
  39. data/test/scaffold_api_controller_generator_test.rb +63 -47
  40. data/test/scaffold_controller_generator_test.rb +47 -11
  41. data/test/test_helper.rb +24 -11
  42. metadata +37 -18
  43. data/.travis.yml +0 -47
  44. data/CHANGELOG.md +0 -283
  45. data/lib/jbuilder/dependency_tracker.rb +0 -61
@@ -1,19 +1,17 @@
1
1
  <% if namespaced? -%>
2
- require_dependency "<%= namespaced_file_path %>/application_controller"
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: [:show, :edit, :update, :destroy]
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,40 @@ 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: <%= "'#{human_name} was successfully created.'" %> }
33
+ format.html { redirect_to <%= redirect_resource_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: <%= "'#{human_name} was successfully updated.'" %> }
46
+ format.html { redirect_to <%= redirect_resource_name %>, notice: <%= %("#{human_name} was successfully updated.") %>, status: :see_other }
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 %>
58
+
63
59
  respond_to do |format|
64
- format.html { redirect_to <%= index_helper %>_url, notice: <%= "'#{human_name} was successfully destroyed.'" %> }
60
+ format.html { redirect_to <%= index_helper %>_path, notice: <%= %("#{human_name} was successfully destroyed.") %>, status: :see_other }
65
61
  format.json { head :no_content }
66
62
  end
67
63
  end
@@ -69,13 +65,19 @@ class <%= controller_class_name %>Controller < ApplicationController
69
65
  private
70
66
  # Use callbacks to share common setup or constraints between actions.
71
67
  def set_<%= singular_table_name %>
68
+ <%- if Rails::VERSION::MAJOR >= 8 -%>
69
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params.expect(:id)") %>
70
+ <%- else -%>
72
71
  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
72
+ <%- end -%>
73
73
  end
74
74
 
75
75
  # Only allow a list of trusted parameters through.
76
76
  def <%= "#{singular_table_name}_params" %>
77
77
  <%- if attributes_names.empty? -%>
78
78
  params.fetch(<%= ":#{singular_table_name}" %>, {})
79
+ <%- elsif Rails::VERSION::MAJOR >= 8 -%>
80
+ params.expect(<%= singular_table_name %>: [ <%= permitted_params %> ])
79
81
  <%- else -%>
80
82
  params.require(<%= ":#{singular_table_name}" %>).permit(<%= permitted_params %>)
81
83
  <%- end -%>
@@ -1 +1 @@
1
- json.array! @<%= plural_table_name %>, partial: "<%= plural_table_name %>/<%= singular_table_name %>", as: :<%= singular_table_name %>
1
+ json.array! @<%= plural_table_name %>, partial: "<%= partial_path_name %>", as: :<%= 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 -%>
@@ -1 +1 @@
1
- json.partial! "<%= plural_table_name %>/<%= singular_table_name %>", <%= singular_table_name %>: @<%= singular_table_name %>
1
+ json.partial! "<%= partial_path_name %>", <%= singular_table_name %>: @<%= singular_table_name %>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Jbuilder
2
4
  class Blank
3
5
  def ==(other)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+ require 'action_view'
5
+ require 'action_view/renderer/collection_renderer'
6
+
7
+ class Jbuilder
8
+ class CollectionRenderer < ::ActionView::CollectionRenderer # :nodoc:
9
+ class ScopedIterator < ::SimpleDelegator # :nodoc:
10
+ include Enumerable
11
+
12
+ def initialize(obj, scope)
13
+ super(obj)
14
+ @scope = scope
15
+ end
16
+
17
+ def each_with_info
18
+ return enum_for(:each_with_info) unless block_given?
19
+
20
+ __getobj__.each_with_info do |object, info|
21
+ @scope.call { yield(object, info) }
22
+ end
23
+ end
24
+ end
25
+
26
+ private_constant :ScopedIterator
27
+
28
+ def initialize(lookup_context, options, &scope)
29
+ super(lookup_context, options)
30
+ @scope = scope
31
+ end
32
+
33
+ private
34
+
35
+ def build_rendered_template(content, template, layout = nil)
36
+ super(content || json.attributes!, template)
37
+ end
38
+
39
+ def build_rendered_collection(templates, _spacer)
40
+ json.merge!(templates.map(&:body))
41
+ end
42
+
43
+ def json
44
+ @options[:locals].fetch(:json)
45
+ end
46
+
47
+ def collection_with_template(view, template, layout, collection)
48
+ super(view, template, layout, ScopedIterator.new(collection, @scope))
49
+ end
50
+ end
51
+
52
+ class EnumerableCompat < ::SimpleDelegator
53
+ # Rails 6.1 requires this.
54
+ def size(*args, &block)
55
+ __getobj__.count(*args, &block)
56
+ end
57
+ end
58
+ end
@@ -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,7 +1,3 @@
1
- Jbuilder = Class.new(begin
2
- require 'active_support/proxy_object'
3
- ActiveSupport::ProxyObject
4
- rescue LoadError
5
- require 'active_support/basic_object'
6
- ActiveSupport::BasicObject
7
- end)
1
+ # frozen_string_literal: true
2
+
3
+ require 'jbuilder/version'
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Jbuilder::DependencyTracker
4
+ EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
5
+
6
+ # Matches:
7
+ # json.partial! "messages/message"
8
+ # json.partial!('messages/message')
9
+ #
10
+ DIRECT_RENDERS = /
11
+ \w+\.partial! # json.partial!
12
+ \(?\s* # optional parenthesis
13
+ (['"])([^'"]+)\1 # quoted value
14
+ /x
15
+
16
+ # Matches:
17
+ # json.partial! partial: "comments/comment"
18
+ # json.comments @post.comments, partial: "comments/comment", as: :comment
19
+ # json.array! @posts, partial: "posts/post", as: :post
20
+ # = render partial: "account"
21
+ #
22
+ INDIRECT_RENDERS = /
23
+ (?::partial\s*=>|partial:) # partial: or :partial =>
24
+ \s* # optional whitespace
25
+ (['"])([^'"]+)\1 # quoted value
26
+ /x
27
+
28
+ def self.call(name, template, view_paths = nil)
29
+ new(name, template, view_paths).dependencies
30
+ end
31
+
32
+ def initialize(name, template, view_paths = nil)
33
+ @name, @template, @view_paths = name, template, view_paths
34
+ end
35
+
36
+ def dependencies
37
+ direct_dependencies + indirect_dependencies + explicit_dependencies
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :name, :template
43
+
44
+ def direct_dependencies
45
+ source.scan(DIRECT_RENDERS).map(&:second)
46
+ end
47
+
48
+ def indirect_dependencies
49
+ source.scan(INDIRECT_RENDERS).map(&:second)
50
+ end
51
+
52
+ def explicit_dependencies
53
+ dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
54
+
55
+ wildcards, explicits = dependencies.partition { |dependency| dependency.end_with?("/*") }
56
+
57
+ (explicits + resolve_directories(wildcards)).uniq
58
+ end
59
+
60
+ def resolve_directories(wildcard_dependencies)
61
+ return [] unless @view_paths
62
+ return [] if wildcard_dependencies.empty?
63
+
64
+ # Remove trailing "/*"
65
+ prefixes = wildcard_dependencies.map { |query| query[0..-3] }
66
+
67
+ @view_paths.flat_map(&:all_template_paths).uniq.filter_map { |path|
68
+ path.to_s if prefixes.include?(path.prefix)
69
+ }.sort
70
+ end
71
+
72
+ def source
73
+ template.source
74
+ end
75
+ end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jbuilder/jbuilder'
4
+ require 'jbuilder/collection_renderer'
2
5
  require 'action_dispatch/http/mime_type'
3
6
  require 'active_support/cache'
4
7
 
@@ -9,17 +12,52 @@ class JbuilderTemplate < Jbuilder
9
12
 
10
13
  self.template_lookup_options = { handlers: [:jbuilder] }
11
14
 
12
- def initialize(context, *args)
15
+ def initialize(context, options = nil)
13
16
  @context = context
14
17
  @cached_root = nil
15
- super(*args)
18
+
19
+ options.nil? ? super() : super(**options)
16
20
  end
17
21
 
22
+ # Generates JSON using the template specified with the `:partial` option. For example, the code below will render
23
+ # the file `views/comments/_comments.json.jbuilder`, and set a local variable comments with all this message's
24
+ # comments, which can be used inside the partial.
25
+ #
26
+ # Example:
27
+ #
28
+ # json.partial! 'comments/comments', comments: @message.comments
29
+ #
30
+ # There are multiple ways to generate a collection of elements as JSON, as ilustrated below:
31
+ #
32
+ # Example:
33
+ #
34
+ # json.array! @posts, partial: 'posts/post', as: :post
35
+ #
36
+ # # or:
37
+ # json.partial! 'posts/post', collection: @posts, as: :post
38
+ #
39
+ # # or:
40
+ # json.partial! partial: 'posts/post', collection: @posts, as: :post
41
+ #
42
+ # # or:
43
+ # json.comments @post.comments, partial: 'comments/comment', as: :comment
44
+ #
45
+ # Aside from that, the `:cached` options is available on Rails >= 6.0. This will cache the rendered results
46
+ # effectively using the multi fetch feature.
47
+ #
48
+ # Example:
49
+ #
50
+ # json.array! @posts, partial: "posts/post", as: :post, cached: true
51
+ #
52
+ # json.comments @post.comments, partial: "comments/comment", as: :comment, cached: true
53
+ #
18
54
  def partial!(*args)
19
55
  if args.one? && _is_active_model?(args.first)
20
56
  _render_active_model_partial args.first
21
57
  else
22
- _render_explicit_partial(*args)
58
+ options = args.extract_options!.dup
59
+ options[:partial] = args.first if args.present?
60
+ _render_partial_with_options options
23
61
  end
24
62
  end
25
63
 
@@ -56,7 +94,7 @@ class JbuilderTemplate < Jbuilder
56
94
  # # json.extra 'This will not work either, the root must be exclusive'
57
95
  def cache_root!(key=nil, options={})
58
96
  if @context.controller.perform_caching
59
- raise "cache_root! can't be used after JSON structures have been defined" if @attributes.present?
97
+ ::Kernel.raise "cache_root! can't be used after JSON structures have been defined" if @attributes.present?
60
98
 
61
99
  @cached_root = _cache_fragment_for([ :root, key ], options) { yield; target! }
62
100
  else
@@ -85,7 +123,9 @@ class JbuilderTemplate < Jbuilder
85
123
  options = args.first
86
124
 
87
125
  if args.one? && _partial_options?(options)
88
- partial! options.merge(collection: collection)
126
+ options = options.dup
127
+ options[:collection] = collection
128
+ _render_partial_with_options options
89
129
  else
90
130
  super
91
131
  end
@@ -95,7 +135,7 @@ class JbuilderTemplate < Jbuilder
95
135
  options = args.first
96
136
 
97
137
  if args.one? && _partial_options?(options)
98
- _set_inline_partial name, object, options
138
+ _set_inline_partial name, object, options.dup
99
139
  else
100
140
  super
101
141
  end
@@ -103,20 +143,35 @@ class JbuilderTemplate < Jbuilder
103
143
 
104
144
  private
105
145
 
146
+ alias_method :method_missing, :set!
147
+
106
148
  def _render_partial_with_options(options)
107
- options.reverse_merge! locals: options.except(:partial, :as, :collection)
108
- options.reverse_merge! ::JbuilderTemplate.template_lookup_options
149
+ options[:locals] ||= options.except(:partial, :as, :collection, :cached)
150
+ options[:handlers] ||= ::JbuilderTemplate.template_lookup_options[:handlers]
109
151
  as = options[:as]
110
152
 
111
153
  if as && options.key?(:collection)
112
- as = as.to_sym
113
- collection = options.delete(:collection)
114
- locals = options.delete(:locals)
115
- array! collection do |member|
116
- member_locals = locals.clone
117
- member_locals.merge! collection: collection
118
- member_locals.merge! as => member
119
- _render_partial options.merge(locals: member_locals)
154
+ collection = options.delete(:collection) || []
155
+ partial = options.delete(:partial)
156
+ options[:locals][:json] = self
157
+ collection = EnumerableCompat.new(collection) if collection.respond_to?(:count) && !collection.respond_to?(:size)
158
+
159
+ if options.has_key?(:layout)
160
+ ::Kernel.raise ::NotImplementedError, "The `:layout' option is not supported in collection rendering."
161
+ end
162
+
163
+ if options.has_key?(:spacer_template)
164
+ ::Kernel.raise ::NotImplementedError, "The `:spacer_template' option is not supported in collection rendering."
165
+ end
166
+
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!
120
175
  end
121
176
  else
122
177
  _render_partial options
@@ -124,7 +179,7 @@ class JbuilderTemplate < Jbuilder
124
179
  end
125
180
 
126
181
  def _render_partial(options)
127
- options[:locals].merge! json: self
182
+ options[:locals][:json] = self
128
183
  @context.render options
129
184
  end
130
185
 
@@ -162,12 +217,7 @@ class JbuilderTemplate < Jbuilder
162
217
 
163
218
  def _fragment_name_with_digest(key, options)
164
219
  if @context.respond_to?(:cache_fragment_name)
165
- # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
166
- # should be used instead.
167
- @context.cache_fragment_name(key, options)
168
- elsif @context.respond_to?(:fragment_name_with_digest)
169
- # Backwards compatibility for period of time when fragment_name_with_digest was made public.
170
- @context.fragment_name_with_digest(key)
220
+ @context.cache_fragment_name(key, **options)
171
221
  else
172
222
  key
173
223
  end
@@ -185,34 +235,18 @@ class JbuilderTemplate < Jbuilder
185
235
  value = if object.nil?
186
236
  []
187
237
  elsif _is_collection?(object)
188
- _scope{ _render_partial_with_options options.merge(collection: object) }
189
- else
190
- locals = ::Hash[options[:as], object]
191
- _scope{ _render_partial_with_options options.merge(locals: locals) }
192
- end
193
-
194
- set! name, value
195
- end
196
-
197
- def _render_explicit_partial(name_or_options, locals = {})
198
- case name_or_options
199
- when ::Hash
200
- # partial! partial: 'name', foo: 'bar'
201
- options = name_or_options
238
+ _scope do
239
+ options[:collection] = object
240
+ _render_partial_with_options options
241
+ end
202
242
  else
203
- # partial! 'name', locals: {foo: 'bar'}
204
- if locals.one? && (locals.keys.first == :locals)
205
- options = locals.merge(partial: name_or_options)
206
- else
207
- options = { partial: name_or_options, locals: locals }
243
+ _scope do
244
+ options[:locals] = { options[:as] => object }
245
+ _render_partial_with_options options
208
246
  end
209
- # partial! 'name', foo: 'bar'
210
- as = locals.delete(:as)
211
- options[:as] = as if as.present?
212
- options[:collection] = locals[:collection] if locals.key?(:collection)
213
247
  end
214
248
 
215
- _render_partial_with_options options
249
+ _set_value name, value
216
250
  end
217
251
 
218
252
  def _render_active_model_partial(object)
@@ -227,7 +261,7 @@ class JbuilderHandler
227
261
  def self.call(template, source = nil)
228
262
  source ||= template.source
229
263
  # this juggling is required to keep line numbers right in the error
230
- %{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source}
264
+ %{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source};
231
265
  json.target! unless (__already_defined && __already_defined != "method")}
232
266
  end
233
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(*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
+ @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,4 +1,6 @@
1
- require 'rails/railtie'
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
2
4
  require 'jbuilder/jbuilder_template'
3
5
 
4
6
  class Jbuilder
@@ -6,31 +8,27 @@ class Jbuilder
6
8
  initializer :jbuilder do
7
9
  ActiveSupport.on_load :action_view do
8
10
  ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
9
- require 'jbuilder/dependency_tracker'
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 self == 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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Jbuilder < BasicObject
4
+ VERSION = "2.14.1"
5
+ end