jbuilder 2.9.1 → 2.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79b2c794b6341ee3d94c4c2d1ed8236e97357dac75dc9e49618a6a885ab35601
4
- data.tar.gz: 4bb8128da8ec6305ae36c3fa866cf19cd1eb08037128b2c3716002525e97014b
3
+ metadata.gz: 3e3eebf3fe3849616361ae7df9556f466eaf84da813756b8690dfbd5c28d41a1
4
+ data.tar.gz: 011c0162b09a94f229673e88bab0d0d466d9552a004afb426f817a02c3af8943
5
5
  SHA512:
6
- metadata.gz: c931310549e6384945735110e6c3a2ce36e566d12d691f33d8a5e68f1dca055eeda1ebe606fb093ec85b4c2481c05ebb7dc639f9209a8e4d324f59dd7b4c8693
7
- data.tar.gz: 277b4c68a0fe426e308f6c5fbc59c8b7453d61291aaf3968e4500532f86e902bbc8ac34970ccd2496935c361584773616a4ff71745b7adbabc752b09ba0da9de
6
+ metadata.gz: 29968e2f35da52dc00db229d0085d77a7d390417bbe3011b005824ff45a1291bca0f45c59d4f40263a3ac236e31ea3fdd0cd78ba01ddef4e51414aea4ac34704
7
+ data.tar.gz: '09df7fb01ce2d128b0f45116cc4f2ccb01469031a51b598f6c17c16f58ddbd0c3059095a1a6761a2f26e328b3960def55752d6ed36cca0e2952e393d712e48b3'
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  tmp
2
+ gemfiles/.bundle
2
3
  gemfiles/*.lock
3
4
  Gemfile.lock
4
5
  .ruby-version
@@ -3,20 +3,18 @@ language: ruby
3
3
  cache: bundler
4
4
 
5
5
  before_install:
6
- - "gem update --system 2.7.9"
7
6
  - "gem install bundler -v '<2'"
8
7
 
9
8
  rvm:
10
9
  - 2.2.10
11
10
  - 2.3.8
12
- - 2.4.6
13
- - 2.5.5
14
- - 2.6.2
11
+ - 2.4.10
12
+ - 2.5.8
13
+ - 2.6.6
14
+ - 2.7.1
15
15
  - ruby-head
16
- - rbx-3.107
17
16
 
18
17
  gemfile:
19
- - gemfiles/rails_4_2.gemfile
20
18
  - gemfiles/rails_5_0.gemfile
21
19
  - gemfiles/rails_5_1.gemfile
22
20
  - gemfiles/rails_5_2.gemfile
@@ -24,41 +22,28 @@ gemfile:
24
22
  - gemfiles/rails_head.gemfile
25
23
 
26
24
  matrix:
27
- include:
28
- - rvm: 1.9
29
- gemfile: gemfiles/rails_4_2.gemfile
30
- - rvm: 2.0
31
- gemfile: gemfiles/rails_4_2.gemfile
32
- - rvm: 2.1
33
- gemfile: gemfiles/rails_4_2.gemfile
34
- - rvm: 2.3
35
- gemfile: gemfiles/rails_4_2.gemfile
36
- - rvm: jruby-19mode
37
- gemfile: gemfiles/rails_4_2.gemfile
38
- - rvm: rbx-3.107
39
- gemfile: gemfiles/rails_4_2.gemfile
40
25
  exclude:
41
- - rvm: 2.4.6
42
- gemfile: gemfiles/rails_4_2.gemfile
43
- - rvm: 2.5.5
44
- gemfile: gemfiles/rails_4_2.gemfile
45
- - rvm: 2.6.2
46
- gemfile: gemfiles/rails_4_2.gemfile
26
+ - rvm: 2.7.1
27
+ gemfile: gemfiles/rails_5_0.gemfile
28
+ - rvm: 2.7.1
29
+ gemfile: gemfiles/rails_5_1.gemfile
30
+ - rvm: 2.2.10
31
+ gemfile: gemfiles/rails_5_2.gemfile
32
+ - rvm: 2.7.1
33
+ gemfile: gemfiles/rails_5_2.gemfile
47
34
  - rvm: 2.2.10
48
35
  gemfile: gemfiles/rails_6_0.gemfile
49
36
  - rvm: 2.3.8
50
37
  gemfile: gemfiles/rails_6_0.gemfile
51
- - rvm: 2.4.6
38
+ - rvm: 2.4.10
52
39
  gemfile: gemfiles/rails_6_0.gemfile
53
40
  - rvm: 2.2.10
54
41
  gemfile: gemfiles/rails_head.gemfile
55
42
  - rvm: 2.3.8
56
43
  gemfile: gemfiles/rails_head.gemfile
57
- - rvm: 2.4.6
44
+ - rvm: 2.4.10
58
45
  gemfile: gemfiles/rails_head.gemfile
59
46
  allow_failures:
60
- - rvm: jruby-19mode
61
- - rvm: rbx-3.107
62
47
  - rvm: ruby-head
63
48
  - gemfile: gemfiles/rails_head.gemfile
64
49
  fast_finish: true
data/Appraisals CHANGED
@@ -1,24 +1,18 @@
1
- appraise "rails-4-2" do
2
- gem "rails", "~> 4.2.0"
1
+ appraise "rails-5-0" do
2
+ gem "rails", "~> 5.0.0"
3
3
  end
4
4
 
5
- if RUBY_VERSION >= "2.2.2"
6
- appraise "rails-5-0" do
7
- gem "rails", "~> 5.0.0"
8
- end
9
-
10
- appraise "rails-5-1" do
11
- gem "rails", "~> 5.1.0"
12
- end
5
+ appraise "rails-5-1" do
6
+ gem "rails", "~> 5.1.0"
7
+ end
13
8
 
14
- appraise "rails-5-2" do
15
- gem "rails", "~> 5.2.0"
16
- end
9
+ appraise "rails-5-2" do
10
+ gem "rails", "~> 5.2.0"
17
11
  end
18
12
 
19
13
  if RUBY_VERSION >= "2.5.0"
20
14
  appraise "rails-6-0" do
21
- gem "rails", "~> 6.0.0.rc1"
15
+ gem "rails", "~> 6.0.0"
22
16
  end
23
17
 
24
18
  appraise "rails-head" do
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ 2.11.1
4
+ ------
5
+
6
+ * Use symbols instead of strings for before_action fitlers [DHH]
7
+ * Slim down comments in generated scaffold code [DHH]
8
+
9
+ 2.11.0
10
+ ------
11
+
12
+ * [Allow jbuilder instance to be passed to #merge!](https://github.com/rails/jbuilder/pull/485)
13
+ * [Fix for key_format! when using nested hashes](https://github.com/rails/jbuilder/pull/486)
14
+ * [Include rich_text, attachment, and attachments fields in json partial](https://github.com/rails/jbuilder/pull/459)
15
+
16
+ 2.10.2
17
+ ------
18
+
19
+ * Update scaffold generator to use double quotes, 422 form error responds, and modern string-of-arrays syntax [DHH]
20
+
21
+ 2.10.1
22
+ ------
23
+
24
+ * Fix keyword arguments warning on Ruby 2.7
25
+
26
+ 2.10.0
27
+ ------
28
+
29
+ * Requires Rails 5+ and Ruby 2.2+
30
+ * Nested hashes are deep-merged
31
+
3
32
  2.9.1
4
33
  -----
5
34
 
@@ -4,18 +4,16 @@ Contributing to Jbuilder
4
4
  [![Build Status](https://api.travis-ci.org/rails/jbuilder.svg?branch=master)][travis]
5
5
  [![Gem Version](https://badge.fury.io/rb/jbuilder.svg)][gem]
6
6
  [![Code Climate](https://codeclimate.com/github/rails/jbuilder/badges/gpa.svg)][codeclimate]
7
- [![Dependencies Status](https://gemnasium.com/rails/jbuilder.svg)][gemnasium]
8
7
 
9
8
  [travis]: https://travis-ci.org/rails/jbuilder
10
9
  [gem]: https://rubygems.org/gems/jbuilder
11
10
  [codeclimate]: https://codeclimate.com/github/rails/jbuilder
12
- [gemnasium]: https://gemnasium.com/rails/jbuilder
13
11
 
14
12
  Jbuilder is work of [many contributors](https://github.com/rails/jbuilder/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/jbuilder/pulls), [propose features and discuss issues](https://github.com/rails/jbuilder/issues).
15
13
 
16
14
  #### Fork the Project
17
15
 
18
- Fork the [project on Github](https://github.com/rails/jbuilder) and check out your copy.
16
+ Fork the [project on GitHub](https://github.com/rails/jbuilder) and check out your copy.
19
17
 
20
18
  ```
21
19
  git clone https://github.com/contributor/jbuilder.git
@@ -5,6 +5,6 @@ source "https://rubygems.org"
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "rails", "~> 6.0.0.rc1"
8
+ gem "rails", "~> 6.0.0"
9
9
 
10
10
  gemspec path: "../"
@@ -1,15 +1,21 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jbuilder'
3
- s.version = '2.9.1'
3
+ s.version = '2.11.1'
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'
7
7
  s.homepage = 'https://github.com/rails/jbuilder'
8
8
  s.license = 'MIT'
9
9
 
10
- s.required_ruby_version = '>= 1.9.3'
10
+ s.required_ruby_version = '>= 2.2.2'
11
11
 
12
- s.add_dependency 'activesupport', '>= 4.2.0'
12
+ s.add_dependency 'activesupport', '>= 5.0.0'
13
+
14
+ if RUBY_ENGINE == 'rbx'
15
+ s.add_development_dependency('racc')
16
+ s.add_development_dependency('json')
17
+ s.add_development_dependency('rubysl')
18
+ end
13
19
 
14
20
  s.files = `git ls-files`.split("\n")
15
21
  s.test_files = `git ls-files -- test/*`.split("\n")
@@ -50,6 +50,10 @@ module Rails
50
50
 
51
51
  attributes.map { |a| ":#{a}"} * ', '
52
52
  end
53
+
54
+ def virtual_attributes
55
+ attributes.select {|name| name.respond_to?(:virtual?) && name.virtual? }
56
+ end
53
57
  end
54
58
  end
55
59
  end
@@ -1,10 +1,10 @@
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, :update, :destroy]
7
+ before_action :set_<%= singular_table_name %>, only: %i[ show update destroy ]
8
8
 
9
9
  # GET <%= route_url %>
10
10
  # GET <%= route_url %>.json
@@ -51,7 +51,7 @@ class <%= controller_class_name %>Controller < ApplicationController
51
51
  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
52
52
  end
53
53
 
54
- # Never trust parameters from the scary internet, only allow the white list through.
54
+ # Only allow a list of trusted parameters through.
55
55
  def <%= "#{singular_table_name}_params" %>
56
56
  <%- if attributes_names.empty? -%>
57
57
  params.fetch(<%= ":#{singular_table_name}" %>, {})
@@ -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,39 @@ 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 @<%= singular_table_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 @<%= singular_table_name %>, notice: <%= %("#{human_name} was successfully updated.") %> }
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 %>
63
58
  respond_to do |format|
64
- format.html { redirect_to <%= index_helper %>_url, notice: <%= "'#{human_name} was successfully destroyed.'" %> }
59
+ format.html { redirect_to <%= index_helper %>_url, notice: <%= %("#{human_name} was successfully destroyed.") %> }
65
60
  format.json { head :no_content }
66
61
  end
67
62
  end
@@ -72,7 +67,7 @@ class <%= controller_class_name %>Controller < ApplicationController
72
67
  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
73
68
  end
74
69
 
75
- # Never trust parameters from the scary internet, only allow the white list through.
70
+ # Only allow a list of trusted parameters through.
76
71
  def <%= "#{singular_table_name}_params" %>
77
72
  <%- if attributes_names.empty? -%>
78
73
  params.fetch(<%= ":#{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 -%>
@@ -4,6 +4,7 @@ require 'jbuilder/key_formatter'
4
4
  require 'jbuilder/errors'
5
5
  require 'json'
6
6
  require 'ostruct'
7
+ require 'active_support/core_ext/hash/deep_merge'
7
8
 
8
9
  class Jbuilder
9
10
  @@key_formatter = nil
@@ -26,12 +27,12 @@ class Jbuilder
26
27
  BLANK = Blank.new
27
28
  NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set
28
29
 
29
- def set!(key, value = BLANK, *args)
30
+ def set!(key, value = BLANK, *args, &block)
30
31
  result = if ::Kernel.block_given?
31
32
  if !_blank?(value)
32
33
  # json.comments @post.comments { |comment| ... }
33
34
  # { "comments": [ { ... }, { ... } ] }
34
- _scope{ array! value, &::Proc.new }
35
+ _scope{ array! value, &block }
35
36
  else
36
37
  # json.comments { ... }
37
38
  # { "comments": ... }
@@ -42,11 +43,11 @@ class Jbuilder
42
43
  # json.age 32
43
44
  # json.person another_jbuilder
44
45
  # { "age": 32, "person": { ... }
45
- value.attributes!
46
+ _format_keys(value.attributes!)
46
47
  else
47
48
  # json.age 32
48
49
  # { "age": 32 }
49
- value
50
+ _format_keys(value)
50
51
  end
51
52
  elsif _is_collection?(value)
52
53
  # json.comments @post.comments, :content, :created_at
@@ -61,9 +62,9 @@ class Jbuilder
61
62
  _set_value key, result
62
63
  end
63
64
 
64
- def method_missing(*args)
65
+ def method_missing(*args, &block)
65
66
  if ::Kernel.block_given?
66
- set!(*args, &::Proc.new)
67
+ set!(*args, &block)
67
68
  else
68
69
  set!(*args)
69
70
  end
@@ -163,7 +164,7 @@ class Jbuilder
163
164
  #
164
165
  # [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ]
165
166
  #
166
- # If you are using Ruby 1.9+, you can use the call syntax instead of an explicit extract! call:
167
+ # You can use the call syntax instead of an explicit extract! call:
167
168
  #
168
169
  # json.(@people) { |person| ... }
169
170
  #
@@ -181,11 +182,11 @@ class Jbuilder
181
182
  # json.array! [1, 2, 3]
182
183
  #
183
184
  # [1,2,3]
184
- def array!(collection = [], *attributes)
185
+ def array!(collection = [], *attributes, &block)
185
186
  array = if collection.nil?
186
187
  []
187
188
  elsif ::Kernel.block_given?
188
- _map_collection(collection, &::Proc.new)
189
+ _map_collection(collection, &block)
189
190
  elsif attributes.any?
190
191
  _map_collection(collection) { |element| extract! element, *attributes }
191
192
  else
@@ -220,9 +221,9 @@ class Jbuilder
220
221
  end
221
222
  end
222
223
 
223
- def call(object, *attributes)
224
+ def call(object, *attributes, &block)
224
225
  if ::Kernel.block_given?
225
- array! object, &::Proc.new
226
+ array! object, &block
226
227
  else
227
228
  extract! object, *attributes
228
229
  end
@@ -240,8 +241,9 @@ class Jbuilder
240
241
  @attributes
241
242
  end
242
243
 
243
- # Merges hash or array into current builder.
244
- def merge!(hash_or_array)
244
+ # Merges hash, array, or Jbuilder instance into current builder.
245
+ def merge!(object)
246
+ hash_or_array = ::Jbuilder === object ? object.attributes! : object
245
247
  @attributes = _merge_values(@attributes, hash_or_array)
246
248
  end
247
249
 
@@ -271,11 +273,11 @@ class Jbuilder
271
273
  if _blank?(updates)
272
274
  current_value
273
275
  elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
274
- updates
276
+ _format_keys(updates)
275
277
  elsif ::Array === current_value && ::Array === updates
276
- current_value + updates
278
+ current_value + _format_keys(updates)
277
279
  elsif ::Hash === current_value && ::Hash === updates
278
- current_value.merge(updates)
280
+ current_value.deep_merge(_format_keys(updates))
279
281
  else
280
282
  raise MergeError.build(current_value, updates)
281
283
  end
@@ -285,6 +287,16 @@ class Jbuilder
285
287
  @key_formatter ? @key_formatter.format(key) : key.to_s
286
288
  end
287
289
 
290
+ def _format_keys(hash_or_array)
291
+ if ::Array === hash_or_array
292
+ hash_or_array.map { |value| _format_keys(value) }
293
+ elsif ::Hash === hash_or_array
294
+ ::Hash[hash_or_array.collect { |k, v| [_key(k), _format_keys(v)] }]
295
+ else
296
+ hash_or_array
297
+ end
298
+ end
299
+
288
300
  def _set_value(key, value)
289
301
  raise NullError.build(key) if @attributes.nil?
290
302
  raise ArrayError.build(key) if ::Array === @attributes
@@ -73,8 +73,8 @@ class JbuilderTemplate < Jbuilder
73
73
  # json.cache_if! !admin?, @person, expires_in: 10.minutes do
74
74
  # json.extract! @person, :name, :age
75
75
  # end
76
- def cache_if!(condition, *args)
77
- condition ? cache!(*args, &::Proc.new) : yield
76
+ def cache_if!(condition, *args, &block)
77
+ condition ? cache!(*args, &block) : yield
78
78
  end
79
79
 
80
80
  def target!
@@ -164,7 +164,7 @@ class JbuilderTemplate < Jbuilder
164
164
  if @context.respond_to?(:cache_fragment_name)
165
165
  # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
166
166
  # should be used instead.
167
- @context.cache_fragment_name(key, options)
167
+ @context.cache_fragment_name(key, **options)
168
168
  elsif @context.respond_to?(:fragment_name_with_digest)
169
169
  # Backwards compatibility for period of time when fragment_name_with_digest was made public.
170
170
  @context.fragment_name_with_digest(key)
@@ -43,4 +43,16 @@ class JbuilderGeneratorTest < Rails::Generators::TestCase
43
43
  assert_no_match %r{:created_at, :updated_at}, content
44
44
  end
45
45
  end
46
+
47
+ if Rails::VERSION::MAJOR >= 6
48
+ test 'handles virtual attributes' do
49
+ run_generator %w(Message content:rich_text video:attachment photos:attachments)
50
+
51
+ assert_file 'app/views/messages/_message.json.jbuilder' do |content|
52
+ assert_match %r{json\.content message\.content\.to_s}, content
53
+ assert_match %r{json\.video url_for\(message\.video\)}, content
54
+ 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
55
+ end
56
+ end
57
+ end
46
58
  end
@@ -99,7 +99,7 @@ class JbuilderTest < ActiveSupport::TestCase
99
99
  assert_equal 32, result['age']
100
100
  end
101
101
 
102
- test 'extracting from object using call style for 1.9' do
102
+ test 'extracting from object using call style' do
103
103
  person = Struct.new(:name, :age).new('David', 32)
104
104
 
105
105
  result = jbuild do |json|
@@ -159,6 +159,25 @@ class JbuilderTest < ActiveSupport::TestCase
159
159
  assert_equal 32, result['author']['age']
160
160
  end
161
161
 
162
+ test 'nested blocks are additive' do
163
+ result = jbuild do |json|
164
+ json.author do
165
+ json.name do
166
+ json.first 'David'
167
+ end
168
+ end
169
+
170
+ json.author do
171
+ json.name do
172
+ json.last 'Heinemeier Hansson'
173
+ end
174
+ end
175
+ end
176
+
177
+ assert_equal 'David', result['author']['name']['first']
178
+ assert_equal 'Heinemeier Hansson', result['author']['name']['last']
179
+ end
180
+
162
181
  test 'support merge! method' do
163
182
  result = jbuild do |json|
164
183
  json.merge! 'foo' => 'bar'
@@ -177,6 +196,18 @@ class JbuilderTest < ActiveSupport::TestCase
177
196
  assert_equal 'Pavel', result['author']['name']
178
197
  end
179
198
 
199
+ test 'support merge! method with Jbuilder instance' do
200
+ obj = jbuild do |json|
201
+ json.foo 'bar'
202
+ end
203
+
204
+ result = jbuild do |json|
205
+ json.merge! obj
206
+ end
207
+
208
+ assert_equal 'bar', result['foo']
209
+ end
210
+
180
211
  test 'blocks are additive via extract syntax' do
181
212
  person = Person.new('Pavel', 27)
182
213
 
@@ -562,6 +593,58 @@ class JbuilderTest < ActiveSupport::TestCase
562
593
  assert_equal ['oats and friends'], result.keys
563
594
  end
564
595
 
596
+ test 'key_format! with merge!' do
597
+ hash = { camel_style: 'for JS' }
598
+ result = jbuild do |json|
599
+ json.key_format! camelize: :lower
600
+ json.merge! hash
601
+ end
602
+
603
+ assert_equal ['camelStyle'], result.keys
604
+ end
605
+
606
+ test 'key_format! with merge! deep' do
607
+ hash = { camel_style: { sub_attr: 'for JS' } }
608
+ result = jbuild do |json|
609
+ json.key_format! camelize: :lower
610
+ json.merge! hash
611
+ end
612
+
613
+ assert_equal ['subAttr'], result['camelStyle'].keys
614
+ end
615
+
616
+ test 'key_format! with set! array of hashes' do
617
+ names = [{ first_name: 'camel', last_name: 'case' }]
618
+ result = jbuild do |json|
619
+ json.key_format! camelize: :lower
620
+ json.set! :names, names
621
+ end
622
+
623
+ assert_equal %w[firstName lastName], result['names'][0].keys
624
+ end
625
+
626
+ test 'key_format! with array! of hashes' do
627
+ names = [{ first_name: 'camel', last_name: 'case' }]
628
+ result = jbuild do |json|
629
+ json.key_format! camelize: :lower
630
+ json.array! names
631
+ end
632
+
633
+ assert_equal %w[firstName lastName], result[0].keys
634
+ end
635
+
636
+ test 'key_format! with merge! array of hashes' do
637
+ names = [{ first_name: 'camel', last_name: 'case' }]
638
+ new_names = [{ first_name: 'snake', last_name: 'case' }]
639
+ result = jbuild do |json|
640
+ json.key_format! camelize: :lower
641
+ json.array! names
642
+ json.merge! new_names
643
+ end
644
+
645
+ assert_equal %w[firstName lastName], result[1].keys
646
+ end
647
+
565
648
  test 'default key_format!' do
566
649
  Jbuilder.key_format camelize: :lower
567
650
  result = jbuild{ |json| json.camel_style 'for JS' }
@@ -55,5 +55,16 @@ if Rails::VERSION::MAJOR > 4
55
55
  assert_match %r{params\.fetch\(:post, \{\}\)}, content
56
56
  end
57
57
  end
58
+
59
+
60
+ if Rails::VERSION::MAJOR >= 6
61
+ test 'handles virtual attributes' do
62
+ run_generator ["Message", "content:rich_text", "video:attachment", "photos:attachments"]
63
+
64
+ assert_file 'app/controllers/messages_controller.rb' do |content|
65
+ assert_match %r{params\.require\(:message\)\.permit\(:content, :video, photos: \[\]\)}, content
66
+ end
67
+ end
68
+ end
58
69
  end
59
70
  end
@@ -31,22 +31,22 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
31
31
  assert_instance_method :create, content do |m|
32
32
  assert_match %r{@post = Post\.new\(post_params\)}, m
33
33
  assert_match %r{@post\.save}, m
34
- assert_match %r{format\.html \{ redirect_to @post, notice: 'Post was successfully created\.' \}}, m
34
+ assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully created\." \}}, m
35
35
  assert_match %r{format\.json \{ render :show, status: :created, location: @post \}}, m
36
- assert_match %r{format\.html \{ render :new \}}, m
36
+ assert_match %r{format\.html \{ render :new, status: :unprocessable_entity \}}, m
37
37
  assert_match %r{format\.json \{ render json: @post\.errors, status: :unprocessable_entity \}}, m
38
38
  end
39
39
 
40
40
  assert_instance_method :update, content do |m|
41
- assert_match %r{format\.html \{ redirect_to @post, notice: 'Post was successfully updated\.' \}}, m
41
+ assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully updated\." \}}, m
42
42
  assert_match %r{format\.json \{ render :show, status: :ok, location: @post \}}, m
43
- assert_match %r{format\.html \{ render :edit \}}, m
43
+ assert_match %r{format\.html \{ render :edit, status: :unprocessable_entity \}}, m
44
44
  assert_match %r{format\.json \{ render json: @post.errors, status: :unprocessable_entity \}}, m
45
45
  end
46
46
 
47
47
  assert_instance_method :destroy, content do |m|
48
48
  assert_match %r{@post\.destroy}, m
49
- assert_match %r{format\.html \{ redirect_to posts_url, notice: 'Post was successfully destroyed\.' \}}, m
49
+ assert_match %r{format\.html \{ redirect_to posts_url, notice: "Post was successfully destroyed\." \}}, m
50
50
  assert_match %r{format\.json \{ head :no_content \}}, m
51
51
  end
52
52
 
@@ -67,4 +67,14 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
67
67
  assert_match %r{params\.fetch\(:post, \{\}\)}, content
68
68
  end
69
69
  end
70
+
71
+ if Rails::VERSION::MAJOR >= 6
72
+ test 'handles virtual attributes' do
73
+ run_generator %w(Message content:rich_text video:attachment photos:attachments)
74
+
75
+ assert_file 'app/controllers/messages_controller.rb' do |content|
76
+ assert_match %r{params\.require\(:message\)\.permit\(:content, :video, photos: \[\]\)}, content
77
+ end
78
+ end
79
+ end
70
80
  end
@@ -11,7 +11,7 @@ require "rails/version"
11
11
  require "jbuilder"
12
12
 
13
13
  require "active_support/testing/autorun"
14
- require "mocha/setup"
14
+ require "mocha/minitest"
15
15
 
16
16
  ActiveSupport.test_order = :random
17
17
 
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.9.1
4
+ version: 2.11.1
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: 2019-05-14 00:00:00.000000000 Z
11
+ date: 2021-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.0
19
+ version: 5.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 4.2.0
26
+ version: 5.0.0
27
27
  description:
28
28
  email: david@basecamp.com
29
29
  executables: []
@@ -39,7 +39,6 @@ files:
39
39
  - MIT-LICENSE
40
40
  - README.md
41
41
  - Rakefile
42
- - gemfiles/rails_4_2.gemfile
43
42
  - gemfiles/rails_5_0.gemfile
44
43
  - gemfiles/rails_5_1.gemfile
45
44
  - gemfiles/rails_5_2.gemfile
@@ -80,14 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
79
  requirements:
81
80
  - - ">="
82
81
  - !ruby/object:Gem::Version
83
- version: 1.9.3
82
+ version: 2.2.2
84
83
  required_rubygems_version: !ruby/object:Gem::Requirement
85
84
  requirements:
86
85
  - - ">="
87
86
  - !ruby/object:Gem::Version
88
87
  version: '0'
89
88
  requirements: []
90
- rubygems_version: 3.0.3
89
+ rubygems_version: 3.1.2
91
90
  signing_key:
92
91
  specification_version: 4
93
92
  summary: Create JSON structures via a Builder-style DSL
@@ -1,10 +0,0 @@
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", "~> 4.2.0"
9
-
10
- gemspec path: "../"