jbuilder 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c134282537dc64d7253ed11314a8ee31402b4fe994626a955b57f308d8bc082
4
- data.tar.gz: eebcdba24d5b41aaf87009296fbb63dd4628677b09955ed7c385e048ad3034a2
3
+ metadata.gz: a7289a23f21f82bfb3eeccd466ec985e8348a9977ed083be43eb8349551e840c
4
+ data.tar.gz: 20d2ba506a7a474d2a32030d91cef03d4345f2332a0753bca685ce6360b30995
5
5
  SHA512:
6
- metadata.gz: 563cfe1ba9e191ed286ca80f77d7ea41737bb402cd257859ec5ffbf3ee77b7a7b041c3cb433d035f10a68a04df2e186140942a98b78b32d7b6d6e64a6514ff44
7
- data.tar.gz: 8c7e23e0e0aa6abdc56f5a14d4b3ea4c7aa4abdc515d3d8fc8e10385c97733e4f5174a861ffc8fda3913623f90dbb878e7547eec917ebb5d9589d46d9d04c3ba
6
+ metadata.gz: fc04dfeb7c16b4547d0f7949b30ec481eb8517da3318550cf6c9f5e8bbc7bdc107c2d8bccc94e0e506741926d14f6798e783ece3640abb6edb323a39f7a691ae
7
+ data.tar.gz: 29a6793c2a3b4318b27b2a0614cc88c2a5e4ca646f39a29cb563d370524bc3c946b9ea8bff114b6a5ae9ea5b4e9d3546e30211f0ada15ad74ff028663933e5d7
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ gemfiles/*.lock
3
3
  Gemfile.lock
4
4
  .ruby-version
5
5
  pkg
6
+ *.gem
data/.travis.yml CHANGED
@@ -1,56 +1,47 @@
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
- - gemfiles/rails_4_2.gemfile
24
19
  - gemfiles/rails_5_0.gemfile
25
20
  - gemfiles/rails_5_1.gemfile
21
+ - gemfiles/rails_5_2.gemfile
22
+ - gemfiles/rails_6_0.gemfile
23
+ - gemfiles/rails_head.gemfile
26
24
 
27
25
  matrix:
26
+ exclude:
27
+ - rvm: 2.2.10
28
+ gemfile: gemfiles/rails_6_0.gemfile
29
+ - rvm: 2.3.8
30
+ gemfile: gemfiles/rails_6_0.gemfile
31
+ - rvm: 2.4.6
32
+ gemfile: gemfiles/rails_6_0.gemfile
33
+ - rvm: 2.2.10
34
+ gemfile: gemfiles/rails_head.gemfile
35
+ - rvm: 2.3.8
36
+ gemfile: gemfiles/rails_head.gemfile
37
+ - rvm: 2.4.6
38
+ gemfile: gemfiles/rails_head.gemfile
28
39
  allow_failures:
29
40
  - rvm: jruby-19mode
30
- - rvm: rbx
41
+ - rvm: rbx-3.107
31
42
  - rvm: ruby-head
43
+ - gemfile: gemfiles/rails_head.gemfile
32
44
  fast_finish: true
33
- exclude:
34
- - rvm: 1.9
35
- gemfile: gemfiles/rails_5_0.gemfile
36
- - rvm: 1.9
37
- gemfile: gemfiles/rails_5_1.gemfile
38
- - 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
44
- - rvm: 2.1
45
- gemfile: gemfiles/rails_5_1.gemfile
46
- - rvm: jruby-19mode
47
- gemfile: gemfiles/rails_5_0.gemfile
48
- - 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
45
 
55
46
  notifications:
56
47
  email: false
data/Appraisals CHANGED
@@ -1,13 +1,21 @@
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", "< 5.1"
5
+ appraise "rails-5-1" do
6
+ gem "rails", "~> 5.1.0"
7
+ end
8
+
9
+ appraise "rails-5-2" do
10
+ gem "rails", "~> 5.2.0"
11
+ end
12
+
13
+ if RUBY_VERSION >= "2.5.0"
14
+ appraise "rails-6-0" do
15
+ gem "rails", "~> 6.0.0"
8
16
  end
9
17
 
10
- appraise "rails-5-1" do
11
- gem "rails", ">= 5.1.0", "< 5.2"
18
+ appraise "rails-head" do
19
+ gem "rails", github: "rails/rails"
12
20
  end
13
21
  end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ 2.10.0
4
+ ----------
5
+
6
+ * Requires Rails 5+ and Ruby 2.2+
7
+ * Nested hashes are deep-merged
8
+
9
+ 2.9.1
10
+ -----
11
+
12
+ * [Respect JSON encoding customizations](https://github.com/rails/jbuilder/commit/e2e8623b08078ad6a2323ce8ecaf642b7afe1166)
13
+
14
+ 2.9.0
15
+ -----
16
+
17
+ * [Fix passing object with partial without locals](https://github.com/rails/jbuilder/pull/435)
18
+ * [Fix deprecation warning in Rails 6.0](https://github.com/rails/jbuilder/pull/453)
19
+ * [Use quotes consistently in generated templates](https://github.com/rails/jbuilder/pull/455)
20
+ * [Allow omitting timestamps from generated partials](https://github.com/rails/jbuilder/pull/448)
21
+ * [Respect changing scaffold generator](https://github.com/rails/jbuilder/pull/458)
22
+ * [Use a symbolic default format for Rails 6.0 forward compatibility](https://github.com/rails/jbuilder/commit/3895a7243f3db292b0bf15513fc05494e6e50576)
23
+ * [Drop MultiJSON in favor of Ruby standard library JSON](https://github.com/rails/jbuilder/commit/b952ae096eb1828b0fcfde06e6ba62311494ec49)
24
+
3
25
  2.8.0
4
26
  -----
5
27
 
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
- 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: "../"
@@ -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", "~> 4.2.0"
8
+ gem "rails", "~> 5.2.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", "~> 6.0.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: "../"
data/jbuilder.gemspec CHANGED
@@ -1,16 +1,15 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jbuilder'
3
- s.version = '2.8.0'
3
+ s.version = '2.10.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'
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'
13
- s.add_dependency 'multi_json', '>= 1.2'
12
+ s.add_dependency 'activesupport', '>= 5.0.0'
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
@@ -51,12 +51,12 @@ 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}" %>, {})
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
@@ -72,12 +72,12 @@ class <%= controller_class_name %>Controller < ApplicationController
72
72
  @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
73
73
  end
74
74
 
75
- # Never trust parameters from the scary internet, only allow the white list through.
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
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)
@@ -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!
@@ -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
data/lib/jbuilder.rb CHANGED
@@ -2,8 +2,9 @@ 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
+ 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": ... }
@@ -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
@@ -247,7 +248,7 @@ class Jbuilder
247
248
 
248
249
  # Encodes the current builder as JSON.
249
250
  def target!
250
- ::MultiJson.dump(@attributes)
251
+ @attributes.to_json
251
252
  end
252
253
 
253
254
  private
@@ -275,7 +276,7 @@ class Jbuilder
275
276
  elsif ::Array === current_value && ::Array === updates
276
277
  current_value + updates
277
278
  elsif ::Hash === current_value && ::Hash === updates
278
- current_value.merge(updates)
279
+ current_value.deep_merge(updates)
279
280
  else
280
281
  raise MergeError.build(current_value, updates)
281
282
  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