jbuilder_reopen 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b5446874dfdda2493ac6fb23c20412fde4268761754ffec2e6a95fabb4bc7862
4
+ data.tar.gz: 5297ce54a75bbcfacfc1b0d237bf164e397045b573a6bc5708358cfeabb7b561
5
+ SHA512:
6
+ metadata.gz: cbf407e0c17497c433e3ebc80083eeb7481c545f41d7dbd1f10df81ce98a54467061c1cf357305fdd73841034d15fe61a482dee3646bbdad356cdf1558a2e4f0
7
+ data.tar.gz: ac94bb0e47acace36e8c1aac753cbd370b34aadb5034b60da9e10204e6f4dab31c8c6708e7c160f9ffc828b75d833f314564168c14be6b68950c2f35de984aca
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ tmp
2
+ gemfiles/*.lock
3
+ Gemfile.lock
4
+ .ruby-version
5
+ pkg
6
+ *.gem
data/.travis.yml ADDED
@@ -0,0 +1,47 @@
1
+ language: ruby
2
+
3
+ cache: bundler
4
+
5
+ before_install:
6
+ - "gem update --system 2.7.9"
7
+ - "gem install bundler -v '<2'"
8
+
9
+ rvm:
10
+ - 2.2.10
11
+ - 2.3.8
12
+ - 2.4.6
13
+ - 2.5.5
14
+ - 2.6.2
15
+ - ruby-head
16
+ - rbx-3.107
17
+
18
+ gemfile:
19
+ - gemfiles/rails_5_0.gemfile
20
+ - gemfiles/rails_5_1.gemfile
21
+ - gemfiles/rails_5_2.gemfile
22
+ - gemfiles/rails_6_0.gemfile
23
+ - gemfiles/rails_head.gemfile
24
+
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
39
+ allow_failures:
40
+ - rvm: jruby-19mode
41
+ - rvm: rbx-3.107
42
+ - rvm: ruby-head
43
+ - gemfile: gemfiles/rails_head.gemfile
44
+ fast_finish: true
45
+
46
+ notifications:
47
+ email: false
data/Appraisals ADDED
@@ -0,0 +1,21 @@
1
+ appraise "rails-5-0" do
2
+ gem "rails", "~> 5.0.0"
3
+ end
4
+
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"
16
+ end
17
+
18
+ appraise "rails-head" do
19
+ gem "rails", github: "rails/rails"
20
+ end
21
+ end
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "mocha", require: false
7
+ gem "appraisal"
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 Jason Tian
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # JbuilderReopen
2
+
3
+ ## Installation
4
+
5
+ gem 'jbuilder_reopen'
6
+
7
+ ## Usage
8
+
9
+ To opmtimise cache, now you can reopen blocks and add additional fields
10
+
11
+ Examples:
12
+
13
+ json.cache! "cache-key" do
14
+ json.posts @posts, partial: "post", as: :post
15
+ end
16
+ json.reopen! ["posts"] do |post|
17
+ json.title post["body"]
18
+ json.reopen! ["author"] do |author|
19
+ json.middle_name author["first_name"]
20
+ end
21
+ end
22
+
23
+ ## Testing
24
+ bundle install
25
+ appraisal install
26
+ appraisal rake test
27
+
28
+ ## Credit
29
+ Thank you! https://github.com/rails/jbuilder
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
6
+ require "appraisal/task"
7
+ Appraisal::Task.new
8
+ task default: :appraisal
9
+ else
10
+ Rake::TestTask.new do |test|
11
+ require "rails/version"
12
+
13
+ test.libs << "test"
14
+
15
+ test.test_files = FileList["test/*_test.rb"]
16
+ end
17
+
18
+ task default: :test
19
+ end
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -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.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", "~> 5.1.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", "~> 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", "~> 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: "../"
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jbuilder_reopen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jbuilder_reopen"
8
+ spec.version = JbuilderReopen::VERSION
9
+ spec.authors = ["Ben Zhang", "Jason Tian"]
10
+ spec.email = ["jason.tian@pixelforcesystems.com.au"]
11
+ spec.summary = "Now you can reopen blocks and add additional fields"
12
+ spec.homepage = "https://www.github.com/jialitian/jbuilder-reopen"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split("\n")
16
+ spec.test_files = `git ls-files -- test/*`.split("\n")
17
+
18
+ spec.required_ruby_version = '>= 2.2.2'
19
+
20
+ spec.add_dependency 'jbuilder', '~> 2.10'
21
+ end
@@ -0,0 +1,6 @@
1
+ require "jbuilder_reopen/version"
2
+ require "jbuilder_reopen/jbuilder_scope"
3
+ require "jbuilder_reopen/jbuilder_template"
4
+
5
+ module JbuilderReopen
6
+ end
@@ -0,0 +1,12 @@
1
+ module JbuilderScope
2
+ def _scope(_attributes=Jbuilder::Blank.new)
3
+ parent_attributes, parent_formatter = @attributes, @key_formatter
4
+ @attributes = _attributes
5
+ yield
6
+ @attributes
7
+ ensure
8
+ @attributes, @key_formatter = parent_attributes, parent_formatter
9
+ end
10
+ end
11
+
12
+ Jbuilder.prepend(JbuilderScope)
@@ -0,0 +1,20 @@
1
+ class JbuilderTemplate
2
+ def reopen!(keys=[], &block)
3
+ keys = keys.dup
4
+ if keys.empty?
5
+ _scope(@attributes) { yield @attributes }
6
+ else
7
+ return if _blank?
8
+ key = keys.shift
9
+ result = if ::Array === @attributes[key]
10
+ @attributes[key].map do |element|
11
+ _scope(element) { reopen!(keys, &block) }
12
+ end
13
+ elsif ::Hash === @attributes[key]
14
+ _scope(@attributes[key]) { reopen!(keys, &block) }
15
+ end
16
+ @attributes[key] = result if result.present?
17
+ @attributes
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module JbuilderReopen
2
+ VERSION = "0.1.3"
3
+ end
@@ -0,0 +1,193 @@
1
+ require "test_helper"
2
+ require "action_view/testing/resolvers"
3
+
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
13
+
14
+ COLLECTION_PARTIAL = <<-JBUILDER
15
+ json.extract! collection, :id, :name
16
+ JBUILDER
17
+
18
+ RACER_PARTIAL = <<-JBUILDER
19
+ json.extract! racer, :id, :name
20
+ JBUILDER
21
+
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,
27
+
28
+ # Ensure we find only Jbuilder partials from within Jbuilder templates.
29
+ "_post.html.erb" => "Hello world!"
30
+ }
31
+
32
+ AUTHORS = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
33
+ POSTS = (1..10).collect { |i| Post.new(i, "Post ##{i}", AUTHORS.next) }
34
+
35
+ setup { Rails.cache.clear }
36
+
37
+ test "reopen array" do
38
+ code = <<-JBUILDER
39
+ json.cache! "cache-key" do
40
+ json.posts @posts, partial: "post", as: :post
41
+ end
42
+ json.reopen! ["posts"] do |post|
43
+ json.title ("title " + post["id"].to_s)
44
+ end
45
+ JBUILDER
46
+ result = render(code, posts: POSTS)
47
+ assert_equal "title 1", result["posts"][0]["title"]
48
+ end
49
+
50
+ test "reopen nested hash" do
51
+ code = <<-JBUILDER
52
+ json.cache! "cache-key" do
53
+ json.posts @posts, partial: "post", as: :post
54
+ end
55
+ json.reopen! ["posts"] do |post|
56
+ json.title post["body"]
57
+ end
58
+ json.reopen! ["posts", "author"] do |author|
59
+ json.middle_name author["first_name"]
60
+ end
61
+ JBUILDER
62
+ result = render(code, posts: POSTS)
63
+ assert_equal "Post #1", result["posts"][0]["title"]
64
+ assert_equal 1, result["posts"][0]["id"]
65
+ assert_equal "Post #1", result["posts"][0]["body"]
66
+ assert_equal "David", result["posts"][2]["author"]["first_name"]
67
+ assert_equal "Heinemeier Hansson", result["posts"][2]["author"]["last_name"]
68
+ assert_equal "David", result["posts"][2]["author"]["middle_name"]
69
+ assert_equal "Pavel", result["posts"][5]["author"]["middle_name"]
70
+ end
71
+
72
+ test "reopen nested reopen" do
73
+ code = <<-JBUILDER
74
+ json.cache! "cache-key" do
75
+ json.posts @posts, partial: "post", as: :post
76
+ end
77
+ json.reopen! ["posts"] do |post|
78
+ json.title post["body"]
79
+ json.reopen! ["author"] do |author|
80
+ json.middle_name author["first_name"]
81
+ end
82
+ end
83
+ JBUILDER
84
+ result = render(code, posts: POSTS)
85
+ assert_equal "Post #1", result["posts"][0]["title"]
86
+ assert_equal 1, result["posts"][0]["id"]
87
+ assert_equal "Post #1", result["posts"][0]["body"]
88
+ assert_equal "David", result["posts"][2]["author"]["first_name"]
89
+ assert_equal "Heinemeier Hansson", result["posts"][2]["author"]["last_name"]
90
+ assert_equal "David", result["posts"][2]["author"]["middle_name"]
91
+ assert_equal "Pavel", result["posts"][5]["author"]["middle_name"]
92
+ end
93
+
94
+ test "reopen nested array" do
95
+ code = <<-JBUILDER
96
+ json.cache! "cache-key" do
97
+ json.authors ["David Heinemeier Hansson", "Pavel Pravosud"] do |author|
98
+ json.name author
99
+ json.posts @posts, partial: "post", as: :post
100
+ end
101
+ end
102
+ json.reopen! ["authors", "posts"] do |_post|
103
+ json.title "test"
104
+ json.body nil
105
+ end
106
+ JBUILDER
107
+ result = render(code, posts: POSTS)
108
+ assert_equal "test", result["authors"][0]["posts"][2]["title"]
109
+ assert_nil result["authors"][0]["posts"][2]["body"]
110
+ end
111
+
112
+ test "raise error if change data type has been overrided" do
113
+ code = <<-JBUILDER
114
+ json.cache! "cache-key" do
115
+ json.posts @posts, partial: "post", as: :post
116
+ end
117
+ json.reopen! ["posts", "body"] do |_body|
118
+ json.title "test"
119
+ end
120
+ JBUILDER
121
+ result = render(code, posts: POSTS)
122
+ assert_nil result["posts"][0]["title"]
123
+ assert_equal "Post #1", result["posts"][0]["body"]
124
+ end
125
+
126
+ test "do nothing if anchor target is not found" do
127
+ code = <<-JBUILDER
128
+ json.cache! "cache-key" do
129
+ json.posts @posts, partial: "post", as: :post
130
+ end
131
+ json.reopen! ["posts", "title"] do |_body|
132
+ json.title "test"
133
+ end
134
+ JBUILDER
135
+ result = render(code, posts: POSTS)
136
+ assert_equal false, result["posts"][0].key?("title")
137
+ assert_equal "Post #1", result["posts"][0]["body"]
138
+ end
139
+
140
+ test "do nothing if anchor target is missing" do
141
+ discussions = [
142
+ {
143
+ title: "Discussion 1",
144
+ posts: POSTS
145
+ },
146
+ {
147
+ title: "Discussion 2",
148
+ posts: []
149
+ }
150
+ ]
151
+ code = <<-JBUILDER
152
+ json.cache! "cache-key" do
153
+ json.discussions @discussions do |discussion|
154
+ json.name discussion[:name]
155
+ json.posts discussion[:posts], partial: "post", as: :post
156
+ end
157
+ end
158
+ json.reopen! ["discussions", "posts", "author"] do |author|
159
+ json.middle_name "test"
160
+ end
161
+ JBUILDER
162
+ result = render(code, discussions: discussions)
163
+ assert_equal "test", result["discussions"][0]["posts"][0]["author"]["middle_name"]
164
+ assert_equal [], result["discussions"][1]["posts"]
165
+ end
166
+
167
+ private
168
+ def render(*args)
169
+ JSON.load render_without_parsing(*args)
170
+ end
171
+
172
+ def render_without_parsing(source, assigns = {})
173
+ view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
174
+ view.render(template: "source.json.jbuilder")
175
+ end
176
+
177
+ def build_view(options = {})
178
+ resolver = ActionView::FixtureResolver.new(options.fetch(:fixtures))
179
+ lookup_context = ActionView::LookupContext.new([ resolver ], {}, [""])
180
+ controller = ActionView::TestCase::TestController.new
181
+
182
+ # TODO: Use with_empty_template_cache unconditionally after dropping support for Rails <6.0.
183
+ view = if ActionView::Base.respond_to?(:with_empty_template_cache)
184
+ ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
185
+ else
186
+ ActionView::Base.new(lookup_context, options.fetch(:assigns, {}), controller)
187
+ end
188
+
189
+ def view.view_cache_dependencies; []; end
190
+
191
+ view
192
+ end
193
+ end
@@ -0,0 +1,35 @@
1
+ require "bundler/setup"
2
+
3
+ require "active_support"
4
+ require "active_support/core_ext/array/access"
5
+ require "active_support/cache/memory_store"
6
+ require "active_support/json"
7
+ require "active_model"
8
+ require "action_view"
9
+ require "rails/version"
10
+
11
+ require "jbuilder"
12
+ require "jbuilder_reopen"
13
+
14
+ require "active_support/testing/autorun"
15
+ require "mocha/setup"
16
+
17
+ ActiveSupport.test_order = :random
18
+
19
+ class << Rails
20
+ def cache
21
+ @cache ||= ActiveSupport::Cache::MemoryStore.new
22
+ end
23
+ end
24
+
25
+ class Post < Struct.new(:id, :body, :author_name); end
26
+
27
+ class Racer < Struct.new(:id, :name)
28
+ extend ActiveModel::Naming
29
+ include ActiveModel::Conversion
30
+ end
31
+
32
+ ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
33
+
34
+ ActionView::Base.remove_possible_method :fragment_name_with_digest
35
+ ActionView::Base.remove_possible_method :cache_fragment_name
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jbuilder_reopen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Ben Zhang
8
+ - Jason Tian
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-03-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: jbuilder
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '2.10'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '2.10'
28
+ description:
29
+ email:
30
+ - jason.tian@pixelforcesystems.com.au
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".travis.yml"
37
+ - Appraisals
38
+ - Gemfile
39
+ - MIT-LICENSE
40
+ - README.md
41
+ - Rakefile
42
+ - gemfiles/.bundle/config
43
+ - gemfiles/rails_5_0.gemfile
44
+ - gemfiles/rails_5_1.gemfile
45
+ - gemfiles/rails_5_2.gemfile
46
+ - gemfiles/rails_6_0.gemfile
47
+ - gemfiles/rails_head.gemfile
48
+ - jbuilder_reopen.gemspec
49
+ - lib/jbuilder_reopen.rb
50
+ - lib/jbuilder_reopen/jbuilder_scope.rb
51
+ - lib/jbuilder_reopen/jbuilder_template.rb
52
+ - lib/jbuilder_reopen/version.rb
53
+ - test/jbuilder_template_test.rb
54
+ - test/test_helper.rb
55
+ homepage: https://www.github.com/jialitian/jbuilder-reopen
56
+ licenses:
57
+ - MIT
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.2.2
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.0.6
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Now you can reopen blocks and add additional fields
78
+ test_files:
79
+ - test/jbuilder_template_test.rb
80
+ - test/test_helper.rb