jbuilder 2.8.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c134282537dc64d7253ed11314a8ee31402b4fe994626a955b57f308d8bc082
4
- data.tar.gz: eebcdba24d5b41aaf87009296fbb63dd4628677b09955ed7c385e048ad3034a2
3
+ metadata.gz: 780a2d0395698145f0e1c9e96a7a2079b70def4be27846b74537ec90786b9495
4
+ data.tar.gz: da6e2704a1060b023c7a78d4539ad39da447dba6e3d7c657834a81badcd47afa
5
5
  SHA512:
6
- metadata.gz: 563cfe1ba9e191ed286ca80f77d7ea41737bb402cd257859ec5ffbf3ee77b7a7b041c3cb433d035f10a68a04df2e186140942a98b78b32d7b6d6e64a6514ff44
7
- data.tar.gz: 8c7e23e0e0aa6abdc56f5a14d4b3ea4c7aa4abdc515d3d8fc8e10385c97733e4f5174a861ffc8fda3913623f90dbb878e7547eec917ebb5d9589d46d9d04c3ba
6
+ metadata.gz: c088b1a55e41c650bccd49901ab964ac9b4b715bdab5d51d68a5b34b6a3bb18adcb37ade32548fa1f69ecd4d2cb29c8f34f747dd4af80daa4c8115e99bd80489
7
+ data.tar.gz: 23e2b31830276ba589c941a484ac6d9b80dc0e3a0f4c4767f8d534f1bdfae5d9e76d1e75a31127103a045afba127c6eb2a7e87f35327860729ef7f08aafdd766
@@ -1,56 +1,60 @@
1
1
  language: ruby
2
2
 
3
- sudo: false
4
3
  cache: bundler
5
4
 
6
5
  before_install:
7
- - gem update --system
8
- - gem install bundler
6
+ - "gem update --system 2.7.9"
7
+ - "gem install bundler -v '<2'"
9
8
 
10
9
  rvm:
11
- - 1.9
12
- - 2.0
13
- - 2.1
14
10
  - 2.2.10
15
- - 2.3.7
16
- - 2.4.4
17
- - 2.5.1
11
+ - 2.3.8
12
+ - 2.4.6
13
+ - 2.5.5
14
+ - 2.6.2
18
15
  - ruby-head
19
- - jruby-19mode
20
- - rbx
16
+ - rbx-3.107
21
17
 
22
18
  gemfile:
23
19
  - gemfiles/rails_4_2.gemfile
24
20
  - gemfiles/rails_5_0.gemfile
25
21
  - gemfiles/rails_5_1.gemfile
22
+ - gemfiles/rails_5_2.gemfile
23
+ - gemfiles/rails_head.gemfile
26
24
 
27
25
  matrix:
28
- allow_failures:
29
- - rvm: jruby-19mode
30
- - rvm: rbx
31
- - rvm: ruby-head
32
- fast_finish: true
33
- exclude:
34
- - rvm: 1.9
35
- gemfile: gemfiles/rails_5_0.gemfile
26
+ include:
36
27
  - rvm: 1.9
37
- gemfile: gemfiles/rails_5_1.gemfile
28
+ gemfile: gemfiles/rails_4_2.gemfile
38
29
  - rvm: 2.0
39
- gemfile: gemfiles/rails_5_0.gemfile
40
- - rvm: 2.0
41
- gemfile: gemfiles/rails_5_1.gemfile
42
- - rvm: 2.1
43
- gemfile: gemfiles/rails_5_0.gemfile
30
+ gemfile: gemfiles/rails_4_2.gemfile
44
31
  - rvm: 2.1
45
- gemfile: gemfiles/rails_5_1.gemfile
32
+ gemfile: gemfiles/rails_4_2.gemfile
33
+ - rvm: 2.3
34
+ gemfile: gemfiles/rails_4_2.gemfile
46
35
  - rvm: jruby-19mode
47
- gemfile: gemfiles/rails_5_0.gemfile
36
+ gemfile: gemfiles/rails_4_2.gemfile
37
+ - rvm: rbx-3.107
38
+ gemfile: gemfiles/rails_4_2.gemfile
39
+ exclude:
40
+ - rvm: 2.4.6
41
+ gemfile: gemfiles/rails_4_2.gemfile
42
+ - rvm: 2.5.5
43
+ gemfile: gemfiles/rails_4_2.gemfile
44
+ - rvm: 2.6.2
45
+ gemfile: gemfiles/rails_4_2.gemfile
46
+ - rvm: 2.2.10
47
+ gemfile: gemfiles/rails_head.gemfile
48
+ - rvm: 2.3.8
49
+ gemfile: gemfiles/rails_head.gemfile
50
+ - rvm: 2.4.6
51
+ gemfile: gemfiles/rails_head.gemfile
52
+ allow_failures:
48
53
  - rvm: jruby-19mode
49
- gemfile: gemfiles/rails_5_1.gemfile
50
- - rvm: rbx
51
- gemfile: gemfiles/rails_5_0.gemfile
52
- - rvm: rbx
53
- gemfile: gemfiles/rails_5_1.gemfile
54
+ - rvm: rbx-3.107
55
+ - rvm: ruby-head
56
+ - gemfile: gemfiles/rails_head.gemfile
57
+ fast_finish: true
54
58
 
55
59
  notifications:
56
60
  email: false
data/Appraisals CHANGED
@@ -1,13 +1,23 @@
1
1
  appraise "rails-4-2" do
2
- gem "rails", "~> 4.2.0"
2
+ gem "rails", "~> 4.2.0"
3
3
  end
4
4
 
5
5
  if RUBY_VERSION >= "2.2.2"
6
6
  appraise "rails-5-0" do
7
- gem "rails", ">= 5.0.0", "< 5.1"
7
+ gem "rails", "~> 5.0.0"
8
8
  end
9
9
 
10
10
  appraise "rails-5-1" do
11
- gem "rails", ">= 5.1.0", "< 5.2"
11
+ gem "rails", "~> 5.1.0"
12
+ end
13
+
14
+ appraise "rails-5-2" do
15
+ gem "rails", "~> 5.2.0"
16
+ end
17
+ end
18
+
19
+ if RUBY_VERSION >= "2.5.0"
20
+ appraise "rails-head" do
21
+ gem "rails", github: "rails/rails"
12
22
  end
13
23
  end
data/Gemfile CHANGED
@@ -5,4 +5,3 @@ gemspec
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "pry"
data/README.md CHANGED
@@ -156,7 +156,6 @@ if current_user.admin?
156
156
  end
157
157
  ```
158
158
 
159
-
160
159
  You can use partials as well. The following will render the file
161
160
  `views/comments/_comments.json.jbuilder`, and set a local variable
162
161
  `comments` with all this message's comments, which you can use inside
@@ -184,6 +183,25 @@ json.partial! partial: 'posts/post', collection: @posts, as: :post
184
183
  json.comments @post.comments, partial: 'comments/comment', as: :comment
185
184
  ```
186
185
 
186
+ The `as: :some_symbol` is used with partials. It will take care of mapping the passed in object to a variable for the partial. If the value is a collection (either implicitly or explicitly by using the `collection:` option, then each value of the collection is passed to the partial as the variable `some_symbol`. If the value is a singular object, then the object is passed to the partial as the variable `some_symbol`.
187
+
188
+ Be sure not to confuse the `as:` option to mean nesting of the partial. For example:
189
+
190
+ ```ruby
191
+ # Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
192
+ # Note, `comment` attributes are "inlined".
193
+ json.partial! @comment, as: :comment
194
+ ```
195
+
196
+ is quite different than:
197
+
198
+ ```ruby
199
+ # comment attributes are nested under a "comment" property
200
+ json.comment do
201
+ json.partial! "/comments/comment.json.jbuilder", comment: @comment
202
+ end
203
+ ```
204
+
187
205
  You can pass any objects into partial templates with or without `:locals` option.
188
206
 
189
207
  ```ruby
@@ -256,21 +274,6 @@ environment.rb for example):
256
274
  Jbuilder.key_format camelize: :lower
257
275
  ```
258
276
 
259
- Faster JSON backends
260
- --------------------
261
-
262
- Jbuilder uses MultiJson, which by default will use the JSON gem. That gem is
263
- currently tangled with ActiveSupport's all-Ruby `#to_json` implementation,
264
- which is slow (fixed in Rails >= 4.1). For faster Jbuilder rendering, you can
265
- specify something like the Yajl JSON generator instead. You'll need to include
266
- the `yajl-ruby` gem in your Gemfile and then set the following configuration
267
- for MultiJson:
268
-
269
- ``` ruby
270
- require 'multi_json'
271
- MultiJson.use :yajl
272
- ```
273
-
274
277
  ## Contributing to Jbuilder
275
278
 
276
279
  Jbuilder is the work of many contributors. You're encouraged to submit pull requests, propose
@@ -5,7 +5,6 @@ source "https://rubygems.org"
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "pry"
9
8
  gem "rails", "~> 4.2.0"
10
9
 
11
10
  gemspec path: "../"
@@ -5,7 +5,6 @@ source "https://rubygems.org"
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "pry"
9
- gem "rails", ">= 5.0.0", "< 5.1"
8
+ gem "rails", "~> 5.0.0"
10
9
 
11
10
  gemspec path: "../"
@@ -5,7 +5,6 @@ source "https://rubygems.org"
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "pry"
9
- gem "rails", ">= 5.1.0", "< 5.2"
8
+ gem "rails", "~> 5.1.0"
10
9
 
11
10
  gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
8
+ gem "rails", "~> 5.2.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
8
+ gem "rails", github: "rails/rails"
9
+
10
+ gemspec path: "../"
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jbuilder'
3
- s.version = '2.8.0'
3
+ s.version = '2.9.0'
4
4
  s.authors = 'David Heinemeier Hansson'
5
5
  s.email = 'david@basecamp.com'
6
6
  s.summary = 'Create JSON structures via a Builder-style DSL'
@@ -10,7 +10,6 @@ Gem::Specification.new do |s|
10
10
  s.required_ruby_version = '>= 1.9.3'
11
11
 
12
12
  s.add_dependency 'activesupport', '>= 4.2.0'
13
- s.add_dependency 'multi_json', '>= 1.2'
14
13
 
15
14
  s.files = `git ls-files`.split("\n")
16
15
  s.test_files = `git ls-files -- test/*`.split("\n")
@@ -10,6 +10,8 @@ module Rails
10
10
 
11
11
  argument :attributes, type: :array, default: [], banner: 'field:type field:type'
12
12
 
13
+ class_option :timestamps, type: :boolean, default: true
14
+
13
15
  def create_root_folder
14
16
  path = File.join('app/views', controller_file_path)
15
17
  empty_directory path unless File.directory?(path)
@@ -33,8 +35,12 @@ module Rails
33
35
  [name, :json, :jbuilder] * '.'
34
36
  end
35
37
 
36
- def attributes_list_with_timestamps
37
- attributes_list(attributes_names + %w(created_at updated_at))
38
+ def full_attributes_list
39
+ if options[:timestamps]
40
+ attributes_list(attributes_names + %w(created_at updated_at))
41
+ else
42
+ attributes_list(attributes_names)
43
+ end
38
44
  end
39
45
 
40
46
  def attributes_list(attributes = attributes_names)
@@ -7,6 +7,12 @@ module Rails
7
7
  source_paths << File.expand_path('../templates', __FILE__)
8
8
 
9
9
  hook_for :jbuilder, type: :boolean, default: true
10
+
11
+ private
12
+
13
+ def permitted_params
14
+ attributes_names.map { |name| ":#{name}" }.join(', ')
15
+ end unless private_method_defined? :permitted_params
10
16
  end
11
17
  end
12
18
  end
@@ -56,7 +56,7 @@ class <%= controller_class_name %>Controller < ApplicationController
56
56
  <%- if attributes_names.empty? -%>
57
57
  params.fetch(<%= ":#{singular_table_name}" %>, {})
58
58
  <%- else -%>
59
- params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
59
+ params.require(<%= ":#{singular_table_name}" %>).permit(<%= permitted_params %>)
60
60
  <%- end -%>
61
61
  end
62
62
  end
@@ -77,7 +77,7 @@ class <%= controller_class_name %>Controller < ApplicationController
77
77
  <%- if attributes_names.empty? -%>
78
78
  params.fetch(<%= ":#{singular_table_name}" %>, {})
79
79
  <%- else -%>
80
- params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
80
+ params.require(<%= ":#{singular_table_name}" %>).permit(<%= permitted_params %>)
81
81
  <%- end -%>
82
82
  end
83
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: "<%= plural_table_name %>/<%= singular_table_name %>", as: :<%= singular_table_name %>
@@ -1,2 +1,2 @@
1
- json.extract! <%= singular_table_name %>, <%= attributes_list_with_timestamps %>
1
+ json.extract! <%= singular_table_name %>, <%= full_attributes_list %>
2
2
  json.url <%= singular_table_name %>_url(<%= singular_table_name %>, format: :json)
@@ -2,7 +2,7 @@ require 'jbuilder/jbuilder'
2
2
  require 'jbuilder/blank'
3
3
  require 'jbuilder/key_formatter'
4
4
  require 'jbuilder/errors'
5
- require 'multi_json'
5
+ require 'json'
6
6
  require 'ostruct'
7
7
 
8
8
  class Jbuilder
@@ -247,7 +247,7 @@ class Jbuilder
247
247
 
248
248
  # Encodes the current builder as JSON.
249
249
  def target!
250
- ::MultiJson.dump(@attributes)
250
+ ::JSON.dump(@attributes)
251
251
  end
252
252
 
253
253
  private
@@ -104,7 +104,7 @@ class JbuilderTemplate < Jbuilder
104
104
  private
105
105
 
106
106
  def _render_partial_with_options(options)
107
- options.reverse_merge! locals: {}
107
+ options.reverse_merge! locals: options.except(:partial, :as, :collection)
108
108
  options.reverse_merge! ::JbuilderTemplate.template_lookup_options
109
109
  as = options[:as]
110
110
 
@@ -222,11 +222,12 @@ end
222
222
 
223
223
  class JbuilderHandler
224
224
  cattr_accessor :default_format
225
- self.default_format = Mime[:json]
225
+ self.default_format = :json
226
226
 
227
- def self.call(template)
227
+ def self.call(template, source = nil)
228
+ source ||= template.source
228
229
  # this juggling is required to keep line numbers right in the error
229
- %{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{template.source}
230
+ %{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{source}
230
231
  json.target! unless (__already_defined && __already_defined != "method")}
231
232
  end
232
233
  end
@@ -21,18 +21,26 @@ class JbuilderGeneratorTest < Rails::Generators::TestCase
21
21
  run_generator
22
22
 
23
23
  assert_file 'app/views/posts/index.json.jbuilder' do |content|
24
- assert_match %r{json.array! @posts, partial: 'posts/post', as: :post}, content
24
+ assert_match %r{json\.array! @posts, partial: "posts/post", as: :post}, content
25
25
  end
26
26
 
27
27
  assert_file 'app/views/posts/show.json.jbuilder' do |content|
28
- assert_match %r{json.partial! \"posts/post\", post: @post}, content
28
+ assert_match %r{json\.partial! "posts/post", post: @post}, content
29
29
  end
30
-
31
- assert_file 'app/views/posts/_post.json.jbuilder' do |content|
30
+
31
+ assert_file 'app/views/posts/_post.json.jbuilder' do |content|
32
32
  assert_match %r{json\.extract! post, :id, :title, :body}, content
33
+ assert_match %r{:created_at, :updated_at}, content
33
34
  assert_match %r{json\.url post_url\(post, format: :json\)}, content
34
35
  end
35
-
36
+ end
36
37
 
38
+ test 'timestamps are not generated in partial with --no-timestamps' do
39
+ run_generator %w(Post title body:text --no-timestamps)
40
+
41
+ assert_file 'app/views/posts/_post.json.jbuilder' do |content|
42
+ assert_match %r{json\.extract! post, :id, :title, :body$}, content
43
+ assert_no_match %r{:created_at, :updated_at}, content
44
+ end
37
45
  end
38
46
  end
@@ -1,457 +1,312 @@
1
1
  require "test_helper"
2
- require "mocha/setup"
3
- require "active_model"
4
- require "action_view"
5
2
  require "action_view/testing/resolvers"
6
- require "active_support/cache"
7
- require "jbuilder/jbuilder_template"
8
-
9
- BLOG_POST_PARTIAL = <<-JBUILDER
10
- json.extract! blog_post, :id, :body
11
- json.author do
12
- first_name, last_name = blog_post.author_name.split(nil, 2)
13
- json.first_name first_name
14
- json.last_name last_name
15
- end
16
- JBUILDER
17
-
18
- COLLECTION_PARTIAL = <<-JBUILDER
19
- json.extract! collection, :id, :name
20
- JBUILDER
21
-
22
- RACER_PARTIAL = <<-JBUILDER
23
- json.extract! racer, :id, :name
24
- JBUILDER
25
-
26
- class Racer
27
- extend ActiveModel::Naming
28
- include ActiveModel::Conversion
29
-
30
- def initialize(id, name)
31
- @id, @name = id, name
32
- end
33
-
34
- attr_reader :id, :name
35
- end
36
-
37
3
 
38
- BlogPost = Struct.new(:id, :body, :author_name)
39
- Collection = Struct.new(:id, :name)
40
- blog_authors = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
41
- BLOG_POST_COLLECTION = Array.new(10){ |i| BlogPost.new(i+1, "post body #{i+1}", blog_authors.next) }
42
- COLLECTION_COLLECTION = Array.new(5){ |i| Collection.new(i+1, "collection #{i+1}") }
43
-
44
- ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
45
-
46
- PARTIALS = {
47
- "_partial.json.jbuilder" => "foo ||= 'hello'; json.content foo",
48
- "_blog_post.json.jbuilder" => BLOG_POST_PARTIAL,
49
- "racers/_racer.json.jbuilder" => RACER_PARTIAL,
50
- "_collection.json.jbuilder" => COLLECTION_PARTIAL
51
- }
52
-
53
- module Rails
54
- def self.cache
55
- @cache ||= ActiveSupport::Cache::MemoryStore.new
56
- end
57
- end
4
+ class JbuilderTemplateTest < ActiveSupport::TestCase
5
+ POST_PARTIAL = <<-JBUILDER
6
+ json.extract! post, :id, :body
7
+ json.author do
8
+ first_name, last_name = post.author_name.split(nil, 2)
9
+ json.first_name first_name
10
+ json.last_name last_name
11
+ end
12
+ JBUILDER
58
13
 
59
- class JbuilderTemplateTest < ActionView::TestCase
60
- setup do
61
- @context = self
62
- Rails.cache.clear
63
- end
14
+ COLLECTION_PARTIAL = <<-JBUILDER
15
+ json.extract! collection, :id, :name
16
+ JBUILDER
64
17
 
65
- def jbuild(source, options = {})
66
- @rendered = []
67
- partials = options.fetch(:partials, PARTIALS).clone
68
- partials["test.json.jbuilder"] = source
69
- resolver = ActionView::FixtureResolver.new(partials)
70
- lookup_context.view_paths = [resolver]
71
- template = ActionView::Template.new(source, "test", JbuilderHandler, virtual_path: "test")
72
- json = template.render(self, {}).strip
73
- MultiJson.load(json)
74
- end
18
+ RACER_PARTIAL = <<-JBUILDER
19
+ json.extract! racer, :id, :name
20
+ JBUILDER
75
21
 
76
- def undef_context_methods(*names)
77
- self.class_eval do
78
- names.each do |name|
79
- undef_method name.to_sym if method_defined?(name.to_sym)
80
- end
81
- end
82
- end
22
+ PARTIALS = {
23
+ "_partial.json.jbuilder" => "json.content content",
24
+ "_post.json.jbuilder" => POST_PARTIAL,
25
+ "racers/_racer.json.jbuilder" => RACER_PARTIAL,
26
+ "_collection.json.jbuilder" => COLLECTION_PARTIAL,
83
27
 
84
- def assert_collection_rendered(result, context = nil)
85
- result = result.fetch(context) if context
28
+ # Ensure we find only Jbuilder partials from within Jbuilder templates.
29
+ "_post.html.erb" => "Hello world!"
30
+ }
86
31
 
87
- assert_equal 10, result.length
88
- assert_equal Array, result.class
89
- assert_equal "post body 5", result[4]["body"]
90
- assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
91
- assert_equal "Pavel", result[5]["author"]["first_name"]
92
- end
32
+ AUTHORS = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
33
+ POSTS = (1..10).collect { |i| Post.new(i, "Post ##{i}", AUTHORS.next) }
93
34
 
94
- test "rendering" do
95
- result = jbuild(<<-JBUILDER)
96
- json.content "hello"
97
- JBUILDER
35
+ setup { Rails.cache.clear }
98
36
 
37
+ test "basic template" do
38
+ result = render('json.content "hello"')
99
39
  assert_equal "hello", result["content"]
100
40
  end
101
41
 
102
- test "key_format! with parameter" do
103
- result = jbuild(<<-JBUILDER)
104
- json.key_format! camelize: [:lower]
105
- json.camel_style "for JS"
106
- JBUILDER
107
-
108
- assert_equal ["camelStyle"], result.keys
109
- end
110
-
111
- test "key_format! propagates to child elements" do
112
- result = jbuild(<<-JBUILDER)
113
- json.key_format! :upcase
114
- json.level1 "one"
115
- json.level2 do
116
- json.value "two"
117
- end
118
- JBUILDER
119
-
120
- assert_equal "one", result["LEVEL1"]
121
- assert_equal "two", result["LEVEL2"]["VALUE"]
42
+ test "partial by name with top-level locals" do
43
+ result = render('json.partial! "partial", content: "hello"')
44
+ assert_equal "hello", result["content"]
122
45
  end
123
46
 
124
- test "partial! renders partial" do
125
- result = jbuild(<<-JBUILDER)
126
- json.partial! "partial"
127
- JBUILDER
128
-
47
+ test "partial by name with nested locals" do
48
+ result = render('json.partial! "partial", locals: { content: "hello" }')
129
49
  assert_equal "hello", result["content"]
130
50
  end
131
51
 
132
- test "partial! + locals via :locals option" do
133
- result = jbuild(<<-JBUILDER)
134
- json.partial! "partial", locals: { foo: "howdy" }
135
- JBUILDER
136
-
137
- assert_equal "howdy", result["content"]
52
+ test "partial by options containing nested locals" do
53
+ result = render('json.partial! partial: "partial", locals: { content: "hello" }')
54
+ assert_equal "hello", result["content"]
138
55
  end
139
56
 
140
- test "partial! + locals without :locals key" do
141
- result = jbuild(<<-JBUILDER)
142
- json.partial! "partial", foo: "goodbye"
143
- JBUILDER
144
-
145
- assert_equal "goodbye", result["content"]
57
+ test "partial by options containing top-level locals" do
58
+ result = render('json.partial! partial: "partial", content: "hello"')
59
+ assert_equal "hello", result["content"]
146
60
  end
147
61
 
148
- test "partial! renders collections" do
149
- result = jbuild(<<-JBUILDER)
150
- json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post
151
- JBUILDER
152
-
153
- assert_collection_rendered result
62
+ test "partial for Active Model" do
63
+ result = render('json.partial! @racer', racer: Racer.new(123, "Chris Harris"))
64
+ assert_equal 123, result["id"]
65
+ assert_equal "Chris Harris", result["name"]
154
66
  end
155
67
 
156
- test "partial! renders collections when as argument is a string" do
157
- result = jbuild(<<-JBUILDER)
158
- json.partial! "blog_post", collection: BLOG_POST_COLLECTION, as: "blog_post"
159
- JBUILDER
160
-
161
- assert_collection_rendered result
68
+ test "partial collection by name with symbol local" do
69
+ result = render('json.partial! "post", collection: @posts, as: :post', posts: POSTS)
70
+ assert_equal 10, result.count
71
+ assert_equal "Post #5", result[4]["body"]
72
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
73
+ assert_equal "Pavel", result[5]["author"]["first_name"]
162
74
  end
163
75
 
164
- test "partial! renders collections as collections" do
165
- result = jbuild(<<-JBUILDER)
166
- json.partial! "collection", collection: COLLECTION_COLLECTION, as: :collection
167
- JBUILDER
168
-
169
- assert_equal 5, result.length
76
+ test "partial collection by name with string local" do
77
+ result = render('json.partial! "post", collection: @posts, as: "post"', posts: POSTS)
78
+ assert_equal 10, result.count
79
+ assert_equal "Post #5", result[4]["body"]
80
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
81
+ assert_equal "Pavel", result[5]["author"]["first_name"]
170
82
  end
171
83
 
172
- test "partial! renders as empty array for nil-collection" do
173
- result = jbuild(<<-JBUILDER)
174
- json.partial! "blog_post", collection: nil, as: :blog_post
175
- JBUILDER
176
-
177
- assert_equal [], result
84
+ test "partial collection by options" do
85
+ result = render('json.partial! partial: "post", collection: @posts, as: :post', posts: POSTS)
86
+ assert_equal 10, result.count
87
+ assert_equal "Post #5", result[4]["body"]
88
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
89
+ assert_equal "Pavel", result[5]["author"]["first_name"]
178
90
  end
179
91
 
180
- test "partial! renders collection (alt. syntax)" do
181
- result = jbuild(<<-JBUILDER)
182
- json.partial! partial: "blog_post", collection: BLOG_POST_COLLECTION, as: :blog_post
183
- JBUILDER
184
-
185
- assert_collection_rendered result
92
+ test "nil partial collection by name" do
93
+ assert_equal [], render('json.partial! "post", collection: @posts, as: :post', posts: nil)
186
94
  end
187
95
 
188
- test "partial! renders as empty array for nil-collection (alt. syntax)" do
189
- result = jbuild(<<-JBUILDER)
190
- json.partial! partial: "blog_post", collection: nil, as: :blog_post
191
- JBUILDER
192
-
193
- assert_equal [], result
96
+ test "nil partial collection by options" do
97
+ assert_equal [], render('json.partial! partial: "post", collection: @posts, as: :post', posts: nil)
194
98
  end
195
99
 
196
- test "render array of partials" do
197
- result = jbuild(<<-JBUILDER)
198
- json.array! BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post
199
- JBUILDER
200
-
201
- assert_collection_rendered result
100
+ test "array of partials" do
101
+ result = render('json.array! @posts, partial: "post", as: :post', posts: POSTS)
102
+ assert_equal 10, result.count
103
+ assert_equal "Post #5", result[4]["body"]
104
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
105
+ assert_equal "Pavel", result[5]["author"]["first_name"]
202
106
  end
203
107
 
204
- test "render array of partials as empty array with nil-collection" do
205
- result = jbuild(<<-JBUILDER)
206
- json.array! nil, partial: "blog_post", as: :blog_post
207
- JBUILDER
208
-
209
- assert_equal [], result
108
+ test "empty array of partials from nil collection" do
109
+ assert_equal [], render('json.array! @posts, partial: "post", as: :post', posts: nil)
210
110
  end
211
111
 
212
- test "render array of partials as a value" do
213
- result = jbuild(<<-JBUILDER)
214
- json.posts BLOG_POST_COLLECTION, partial: "blog_post", as: :blog_post
215
- JBUILDER
216
-
217
- assert_collection_rendered result, "posts"
112
+ test "array of partials under key" do
113
+ result = render('json.posts @posts, partial: "post", as: :post', posts: POSTS)
114
+ assert_equal 10, result["posts"].count
115
+ assert_equal "Post #5", result["posts"][4]["body"]
116
+ assert_equal "Heinemeier Hansson", result["posts"][2]["author"]["last_name"]
117
+ assert_equal "Pavel", result["posts"][5]["author"]["first_name"]
218
118
  end
219
119
 
220
- test "render as empty array if partials as a nil value" do
221
- result = jbuild <<-JBUILDER
222
- json.posts nil, partial: "blog_post", as: :blog_post
223
- JBUILDER
224
-
120
+ test "empty array of partials under key from nil collection" do
121
+ result = render('json.posts @posts, partial: "post", as: :post', posts: nil)
225
122
  assert_equal [], result["posts"]
226
123
  end
227
124
 
228
- test "cache an empty block" do
229
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
230
-
231
- jbuild <<-JBUILDER
232
- json.cache! "nothing" do
125
+ test "object fragment caching" do
126
+ render(<<-JBUILDER)
127
+ json.cache! "cache-key" do
128
+ json.name "Hit"
233
129
  end
234
130
  JBUILDER
235
131
 
236
- result = nil
237
-
238
- assert_nothing_raised do
239
- result = jbuild(<<-JBUILDER)
240
- json.foo "bar"
241
- json.cache! "nothing" do
242
- end
243
- JBUILDER
244
- end
245
-
246
- assert_equal "bar", result["foo"]
132
+ hit = render('json.cache! "cache-key" do; end')
133
+ assert_equal "Hit", hit["name"]
247
134
  end
248
135
 
249
- test "fragment caching a JSON object" do
250
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
251
-
252
- jbuild <<-JBUILDER
253
- json.cache! "cachekey" do
254
- json.name "Cache"
136
+ test "conditional object fragment caching" do
137
+ render(<<-JBUILDER)
138
+ json.cache_if! true, "cache-key" do
139
+ json.a "Hit"
255
140
  end
256
- JBUILDER
257
141
 
258
- result = jbuild(<<-JBUILDER)
259
- json.cache! "cachekey" do
260
- json.name "Miss"
142
+ json.cache_if! false, "cache-key" do
143
+ json.b "Hit"
261
144
  end
262
145
  JBUILDER
263
146
 
264
- assert_equal "Cache", result["name"]
265
- end
266
-
267
- test "conditionally fragment caching a JSON object" do
268
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
269
-
270
- jbuild <<-JBUILDER
271
- json.cache_if! true, "cachekey" do
272
- json.test1 "Cache"
147
+ result = render(<<-JBUILDER)
148
+ json.cache_if! true, "cache-key" do
149
+ json.a "Miss"
273
150
  end
274
- json.cache_if! false, "cachekey" do
275
- json.test2 "Cache"
276
- end
277
- JBUILDER
278
151
 
279
- result = jbuild(<<-JBUILDER)
280
- json.cache_if! true, "cachekey" do
281
- json.test1 "Miss"
282
- end
283
- json.cache_if! false, "cachekey" do
284
- json.test2 "Miss"
152
+ json.cache_if! false, "cache-key" do
153
+ json.b "Miss"
285
154
  end
286
155
  JBUILDER
287
156
 
288
- assert_equal "Cache", result["test1"]
289
- assert_equal "Miss", result["test2"]
157
+ assert_equal "Hit", result["a"]
158
+ assert_equal "Miss", result["b"]
290
159
  end
291
160
 
292
- test "fragment caching deserializes an array" do
293
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
161
+ test "object fragment caching with expiry" do
162
+ travel_to "2018-05-12 11:29:00 -0400"
294
163
 
295
- jbuild <<-JBUILDER
296
- json.cache! "cachekey" do
297
- json.array! %w[a b c]
164
+ render <<-JBUILDER
165
+ json.cache! "cache-key", expires_in: 1.minute do
166
+ json.name "Hit"
298
167
  end
299
168
  JBUILDER
300
169
 
301
- result = jbuild(<<-JBUILDER)
302
- json.cache! "cachekey" do
303
- json.array! %w[1 2 3]
170
+ travel 30.seconds
171
+
172
+ result = render(<<-JBUILDER)
173
+ json.cache! "cache-key", expires_in: 1.minute do
174
+ json.name "Miss"
304
175
  end
305
176
  JBUILDER
306
177
 
307
- assert_equal %w[a b c], result
308
- end
309
-
310
- test "fragment caching works with current cache digests" do
311
- undef_context_methods :fragment_name_with_digest
178
+ assert_equal "Hit", result["name"]
312
179
 
313
- @context.expects :cache_fragment_name
314
- ActiveSupport::Cache.expects :expand_cache_key
180
+ travel 31.seconds
315
181
 
316
- jbuild <<-JBUILDER
317
- json.cache! "cachekey" do
318
- json.name "Cache"
182
+ result = render(<<-JBUILDER)
183
+ json.cache! "cache-key", expires_in: 1.minute do
184
+ json.name "Miss"
319
185
  end
320
186
  JBUILDER
321
- end
322
187
 
323
- test "fragment caching uses combined_fragment_cache_key" do
324
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
325
-
326
- @context.expects(:combined_fragment_cache_key).with("cachekey")
188
+ assert_equal "Miss", result["name"]
189
+ end
327
190
 
328
- jbuild <<-JBUILDER
329
- json.cache! "cachekey" do
330
- json.name "Cache"
191
+ test "object root caching" do
192
+ render <<-JBUILDER
193
+ json.cache_root! "cache-key" do
194
+ json.name "Hit"
331
195
  end
332
196
  JBUILDER
333
- end
334
-
335
- test "fragment caching instrumentation" do
336
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
337
197
 
338
- payloads = {}
339
- ActiveSupport::Notifications.subscribe("read_fragment.action_controller") { |*args| payloads[:read_fragment] = args.last }
340
- ActiveSupport::Notifications.subscribe("write_fragment.action_controller") { |*args| payloads[:write_fragment] = args.last }
198
+ assert_equal JSON.dump(name: "Hit"), Rails.cache.read("jbuilder/root/cache-key")
341
199
 
342
- jbuild <<-JBUILDER
343
- json.cache! "cachekey" do
344
- json.name "Cache"
200
+ result = render(<<-JBUILDER)
201
+ json.cache_root! "cache-key" do
202
+ json.name "Miss"
345
203
  end
346
204
  JBUILDER
347
205
 
348
- assert_equal "jbuilder/cachekey", payloads[:read_fragment][:key]
349
- assert_equal "jbuilder/cachekey", payloads[:write_fragment][:key]
206
+ assert_equal "Hit", result["name"]
350
207
  end
351
208
 
352
- test "current cache digest option accepts options" do
353
- undef_context_methods :fragment_name_with_digest
354
-
355
- @context.expects(:cache_fragment_name).with("cachekey", skip_digest: true)
356
- ActiveSupport::Cache.expects :expand_cache_key
357
-
358
- jbuild <<-JBUILDER
359
- json.cache! "cachekey", skip_digest: true do
360
- json.name "Cache"
209
+ test "array fragment caching" do
210
+ render <<-JBUILDER
211
+ json.cache! "cache-key" do
212
+ json.array! %w[ a b c ]
361
213
  end
362
214
  JBUILDER
363
- end
364
215
 
365
- test "fragment caching accepts expires_in option" do
366
- undef_context_methods :fragment_name_with_digest
367
-
368
- @context.expects(:cache_fragment_name).with("cachekey", {})
369
-
370
- jbuild <<-JBUILDER
371
- json.cache! "cachekey", expires_in: 1.minute do
372
- json.name "Cache"
373
- end
374
- JBUILDER
216
+ assert_equal %w[ a b c ], render('json.cache! "cache-key" do; end')
375
217
  end
376
218
 
377
- test "caching root structure" do
378
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
379
-
380
- cache_miss_result = jbuild <<-JBUILDER
381
- json.cache_root! "cachekey" do
382
- json.name "Miss"
219
+ test "array root caching" do
220
+ render <<-JBUILDER
221
+ json.cache_root! "cache-key" do
222
+ json.array! %w[ a b c ]
383
223
  end
384
224
  JBUILDER
385
225
 
386
- cache_hit_result = jbuild <<-JBUILDER
387
- json.cache_root! "cachekey" do
388
- json.name "Hit"
226
+ assert_equal JSON.dump(%w[ a b c ]), Rails.cache.read("jbuilder/root/cache-key")
227
+
228
+ assert_equal %w[ a b c ], render(<<-JBUILDER)
229
+ json.cache_root! "cache-key" do
230
+ json.array! %w[ d e f ]
389
231
  end
390
232
  JBUILDER
391
-
392
- assert_equal cache_miss_result, cache_hit_result
393
233
  end
394
234
 
395
- test "failing to cache root after attributes have been defined" do
235
+ test "failing to cache root after JSON structures have been defined" do
396
236
  assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do
397
- jbuild <<-JBUILDER
237
+ render <<-JBUILDER
398
238
  json.name "Kaboom"
399
- json.cache_root! "cachekey" do
239
+ json.cache_root! "cache-key" do
400
240
  json.name "Miss"
401
241
  end
402
242
  JBUILDER
403
243
  end
404
244
  end
405
245
 
406
- test "does not perform caching when controller.perform_caching is false" do
407
- controller.perform_caching = false
246
+ test "empty fragment caching" do
247
+ render 'json.cache! "nothing" do; end'
408
248
 
409
- jbuild <<-JBUILDER
410
- json.cache! "cachekey" do
411
- json.name "Cache"
412
- end
413
- JBUILDER
249
+ result = nil
250
+
251
+ assert_nothing_raised do
252
+ result = render(<<-JBUILDER)
253
+ json.foo "bar"
254
+ json.cache! "nothing" do; end
255
+ JBUILDER
256
+ end
414
257
 
415
- assert_equal Rails.cache.inspect[/entries=(\d+)/, 1], "0"
258
+ assert_equal "bar", result["foo"]
416
259
  end
417
260
 
418
- test "invokes templates via params via set!" do
419
- @post = BLOG_POST_COLLECTION.first
261
+ test "cache instrumentation" do
262
+ payloads = {}
420
263
 
421
- result = jbuild(<<-JBUILDER)
422
- json.post @post, partial: "blog_post", as: :blog_post
264
+ ActiveSupport::Notifications.subscribe("read_fragment.action_controller") { |*args| payloads[:read] = args.last }
265
+ ActiveSupport::Notifications.subscribe("write_fragment.action_controller") { |*args| payloads[:write] = args.last }
266
+
267
+ render <<-JBUILDER
268
+ json.cache! "cache-key" do
269
+ json.name "Cache"
270
+ end
423
271
  JBUILDER
424
272
 
425
- assert_equal 1, result["post"]["id"]
426
- assert_equal "post body 1", result["post"]["body"]
427
- assert_equal "David", result["post"]["author"]["first_name"]
273
+ assert_equal "jbuilder/cache-key", payloads[:read][:key]
274
+ assert_equal "jbuilder/cache-key", payloads[:write][:key]
428
275
  end
429
276
 
430
- test "invokes templates implicitly for ActiveModel objects" do
431
- @racer = Racer.new(123, "Chris Harris")
432
-
433
- result = jbuild(<<-JBUILDER)
434
- json.partial! @racer
277
+ test "camelized keys" do
278
+ result = render(<<-JBUILDER)
279
+ json.key_format! camelize: [:lower]
280
+ json.first_name "David"
435
281
  JBUILDER
436
282
 
437
- assert_equal %w[id name], result.keys
438
- assert_equal 123, result["id"]
439
- assert_equal "Chris Harris", result["name"]
283
+ assert_equal "David", result["firstName"]
440
284
  end
441
285
 
442
- test "renders partial via set! with same name as HTML partial" do
443
- partials = {
444
- "_blog_post.html.erb" => "Hello!",
445
- "_blog_post.json.jbuilder" => BLOG_POST_PARTIAL
446
- }
286
+ private
287
+ def render(*args)
288
+ JSON.load render_without_parsing(*args)
289
+ end
447
290
 
448
- @post = BLOG_POST_COLLECTION.first
291
+ def render_without_parsing(source, assigns = {})
292
+ view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
293
+ view.render(template: "source.json.jbuilder")
294
+ end
449
295
 
450
- result = jbuild(<<-JBUILDER, partials: partials)
451
- json.post @post, partial: "blog_post", as: :blog_post
452
- JBUILDER
296
+ def build_view(options = {})
297
+ resolver = ActionView::FixtureResolver.new(options.fetch(:fixtures))
298
+ lookup_context = ActionView::LookupContext.new([ resolver ], {}, [""])
299
+ controller = ActionView::TestCase::TestController.new
453
300
 
454
- assert_not_nil result["post"]
455
- assert_equal 1, result["post"]["id"]
456
- end
301
+ # TODO: Use with_empty_template_cache unconditionally after dropping support for Rails <6.0.
302
+ view = if ActionView::Base.respond_to?(:with_empty_template_cache)
303
+ ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
304
+ else
305
+ ActionView::Base.new(lookup_context, options.fetch(:assigns, {}), controller)
306
+ end
307
+
308
+ def view.view_cache_dependencies; []; end
309
+
310
+ view
311
+ end
457
312
  end
@@ -75,7 +75,7 @@ class JbuilderTest < ActiveSupport::TestCase
75
75
  end
76
76
 
77
77
  assert result.has_key?('content')
78
- assert_equal nil, result['content']
78
+ assert_nil result['content']
79
79
  end
80
80
 
81
81
  test 'multiple keys' do
@@ -6,7 +6,7 @@ if Rails::VERSION::MAJOR > 4
6
6
 
7
7
  class ScaffoldApiControllerGeneratorTest < Rails::Generators::TestCase
8
8
  tests Rails::Generators::ScaffoldControllerGenerator
9
- arguments %w(Post title body:text --api)
9
+ arguments %w(Post title body:text images:attachments --api)
10
10
  destination File.expand_path('../tmp', __FILE__)
11
11
  setup :prepare_destination
12
12
 
@@ -39,7 +39,11 @@ if Rails::VERSION::MAJOR > 4
39
39
  end
40
40
 
41
41
  assert_match %r{def post_params}, content
42
- assert_match %r{params\.require\(:post\)\.permit\(:title, :body\)}, content
42
+ if Rails::VERSION::MAJOR >= 6
43
+ assert_match %r{params\.require\(:post\)\.permit\(:title, :body, images: \[\]\)}, content
44
+ else
45
+ assert_match %r{params\.require\(:post\)\.permit\(:title, :body, :images\)}, content
46
+ end
43
47
  end
44
48
  end
45
49
 
@@ -4,7 +4,7 @@ require 'generators/rails/scaffold_controller_generator'
4
4
 
5
5
  class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
6
6
  tests Rails::Generators::ScaffoldControllerGenerator
7
- arguments %w(Post title body:text)
7
+ arguments %w(Post title body:text images:attachments)
8
8
  destination File.expand_path('../tmp', __FILE__)
9
9
  setup :prepare_destination
10
10
 
@@ -51,7 +51,11 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
51
51
  end
52
52
 
53
53
  assert_match %r{def post_params}, content
54
- assert_match %r{params\.require\(:post\)\.permit\(:title, :body\)}, content
54
+ if Rails::VERSION::MAJOR >= 6
55
+ assert_match %r{params\.require\(:post\)\.permit\(:title, :body, images: \[\]\)}, content
56
+ else
57
+ assert_match %r{params\.require\(:post\)\.permit\(:title, :body, :images\)}, content
58
+ end
55
59
  end
56
60
  end
57
61
 
@@ -1,16 +1,33 @@
1
1
  require "bundler/setup"
2
+
2
3
  require "active_support"
3
- require 'active_support/core_ext/array/access'
4
+ require "active_support/core_ext/array/access"
5
+ require "active_support/cache/memory_store"
6
+ require "active_model"
7
+ require "action_view"
4
8
  require "rails/version"
9
+
5
10
  require "jbuilder"
6
11
 
7
- if Rails::VERSION::STRING > "4.0"
8
- require "active_support/testing/autorun"
9
- else
10
- require "test/unit"
12
+ require "active_support/testing/autorun"
13
+ require "mocha/setup"
14
+
15
+ ActiveSupport.test_order = :random
16
+
17
+ class << Rails
18
+ def cache
19
+ @cache ||= ActiveSupport::Cache::MemoryStore.new
20
+ end
11
21
  end
12
22
 
23
+ class Post < Struct.new(:id, :body, :author_name); end
13
24
 
14
- if ActiveSupport.respond_to?(:test_order=)
15
- ActiveSupport.test_order = :random
25
+ class Racer < Struct.new(:id, :name)
26
+ extend ActiveModel::Naming
27
+ include ActiveModel::Conversion
16
28
  end
29
+
30
+ ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
31
+
32
+ ActionView::Base.remove_possible_method :fragment_name_with_digest
33
+ ActionView::Base.remove_possible_method :cache_fragment_name
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-05 00:00:00.000000000 Z
11
+ date: 2019-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 4.2.0
27
- - !ruby/object:Gem::Dependency
28
- name: multi_json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '1.2'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '1.2'
41
27
  description:
42
28
  email: david@basecamp.com
43
29
  executables: []
@@ -56,6 +42,8 @@ files:
56
42
  - gemfiles/rails_4_2.gemfile
57
43
  - gemfiles/rails_5_0.gemfile
58
44
  - gemfiles/rails_5_1.gemfile
45
+ - gemfiles/rails_5_2.gemfile
46
+ - gemfiles/rails_head.gemfile
59
47
  - jbuilder.gemspec
60
48
  - lib/generators/rails/jbuilder_generator.rb
61
49
  - lib/generators/rails/scaffold_controller_generator.rb
@@ -98,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
86
  - !ruby/object:Gem::Version
99
87
  version: '0'
100
88
  requirements: []
101
- rubyforge_project:
102
- rubygems_version: 2.7.6
89
+ rubygems_version: 3.0.3
103
90
  signing_key:
104
91
  specification_version: 4
105
92
  summary: Create JSON structures via a Builder-style DSL