jbuilder-jpartial 1.0.2 → 1.1.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
  SHA1:
3
- metadata.gz: a65d95a34e52d2bfbba166e44f08f537342ff7e6
4
- data.tar.gz: 8bc8ffd3a466815047991e8484a937d850bc3dbc
3
+ metadata.gz: 484a3494bea19dd423cd1bfec8942c5e47475541
4
+ data.tar.gz: 1dc470a7f1a92377a054fe33031757b8398f4e08
5
5
  SHA512:
6
- metadata.gz: 98a6bfcbb32d121bb3a154745a65d1b0879dc21c46746ebdecb4ee8745f96512b9de3513206f5872e736889faeaa90b83167045c4fc110183d7bc29d4e569537
7
- data.tar.gz: bb6c0bd057fd945894fb1275fa8614b2eee1b34a674eed14fffb6b5f33cd1ba4322a3d334dc5471b16d30ba7a95489b653bf2fb606eb6f16975adabbc6406797
6
+ metadata.gz: f0611e2298872183b2458663ece24039a8b3b205944ddd7dfa586ebfb38d562ece8fed535038d81a36dffa1f4a18d115231348de395aa7fbac542bfb227d4c3d
7
+ data.tar.gz: 792df2214b9d1869cb3d55b97da7a6c4b0506511d1a1ffbf864f32c7f699535a0391603e345f330932b6cf462d0083e80fecdb35b897cc5efe51bce1e8d8901a
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ 1.1
4
+ -----
5
+ * Do less monkey patching on the original Jbuilder class. Only add the partial methods defined by the user, otherwise leave Jbuilder alone and leave the rest to a proxy class.
6
+ * Make sure all view helper methods are available in partials, not just route helpers.
7
+ * Add Rails generator for initializer file.
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Jbuilder::Jpartial
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/jbuilder-jpartial.svg)](https://badge.fury.io/rb/jbuilder-jpartial)
4
+ [![Build Status](https://travis-ci.org/msimonborg/jbuilder-jpartial.svg?branch=master)](https://travis-ci.org/msimonborg/jbuilder-jpartial)
5
+
3
6
  A lightweight library that provides a simple DSL for faster partial rendering with Jbuilder.
4
7
 
5
8
  ## Installation
@@ -17,7 +20,7 @@ And then execute:
17
20
  Or install it yourself as:
18
21
 
19
22
  $ gem install jbuilder-jpartial
20
-
23
+
21
24
  require 'jbuilder/jpartial'
22
25
 
23
26
  ## Usage
@@ -72,13 +75,18 @@ end
72
75
  #### Why?
73
76
  When partials are used with `Jbuilder` render times and memory usage can skyrocket quickly with the number of records, i.e. the number of partials rendered.
74
77
 
75
- Using a simple DSL, `Jbuilder::Jpartial` lets you define your partials in a familiar way while dramatically reducing overhead.
78
+ Using a simple DSL, `Jbuilder::Jpartial` lets you define your partials in a familiar way while dramatically reducing overhead.
76
79
 
77
80
  The result is faster rendering and lower memory usage, while still being able to leverage the advantages of Jbuilder. In the above example, if we had used standard Jbuilder partials those templates would have to be rendered once for each `post` and/or `comment`. If you have 50 posts, each with 50 comments, that's 2,550 templates rendered! Using `Jbuilder::Jpartial`, the partial files are each only called when the partial is initialized. After that, all of the partial rendering is taken care of in the abstract from the original file. In our example, we hit `json.partial! 'post'` once and `json.partial! 'comments/comment'` only once for each `post`, cutting 2,550 template renders down to 51.
78
81
 
79
82
  Alternatively you can define all partials in one initializer file and call them wherever you need them: from within other partial definitions or anywhere you use `Jbuilder` in your views. The big advantage here is since they're initialized at start up, you don't need to call any additional view templates to render the partials. Using the same example as above:
80
83
 
81
- #### In `app/config/initializers/jpartial.rb`
84
+ #### First generate the file
85
+
86
+ $ rails generate jpartial
87
+
88
+
89
+ #### Then in `app/config/initializers/jpartial.rb`
82
90
  ```ruby
83
91
  Jbuilder::Jpartial.configure do |jpartial|
84
92
  jpartial._post do |post|
@@ -89,7 +97,7 @@ Jbuilder::Jpartial.configure do |jpartial|
89
97
  json._comment comment
90
98
  end
91
99
  end
92
-
100
+
93
101
  jpartial._comment do |comment|
94
102
  json.content comment.content
95
103
  json.author comment.author.name
@@ -109,13 +117,13 @@ Notice that when using this method, we don't make any calls like `json.partial!
109
117
  We've now cut our template renders down to only 1 from the original 2,550. The only real disadvantage is it bucks the regular Rails file structure conventions for partials. C'est la vie.
110
118
 
111
119
  #### How?
112
- Each method you call on `jpartial` defines a Jbuilder method of the same name. The objects you will pass to that method are yielded to the block. Inside the block you can use plain old Jbuilder syntax.
120
+ Each method you call on `jpartial` defines a Jbuilder method of the same name. The objects you will pass to that method are yielded to the block. Inside the block you can use plain old Jbuilder syntax, and access any of the helper methods available in your views.
113
121
 
114
122
  e.g.
115
123
 
116
124
  ```ruby
117
125
  jpartial._post do |post|
118
- json.title post.title
126
+ json.post_url post_url(post)
119
127
  end
120
128
  ```
121
129
 
@@ -145,15 +153,16 @@ end
145
153
 
146
154
  Now you can call `json._post @post, author: @author`
147
155
 
148
- Again, if you're defining all of your partials in one config file, the extra call to a partial template is not necessary.
156
+ Again, if you're defining all of your partials in one config file (best performance), the extra call to a partial template is not necessary.
149
157
 
158
+ #### `config/initializers/jpartial.rb`
150
159
  ```ruby
151
160
  Jbuilder::Jpartial.configure do |jpartial|
152
161
  jpartial._post do |post, author:|
153
162
  json.title post.title
154
163
  json._author author
155
164
  end
156
-
165
+
157
166
  jpartial._author do |author|
158
167
  json.name author.name
159
168
  end
@@ -161,11 +170,6 @@ end
161
170
  ```
162
171
 
163
172
  However unlikely, if you try to name a partial with the same name as a method already defined by Jbuilder it will throw an error at start up. Just pick a different name, like `#whatever_partial` instead of `#whatever`.
164
-
165
- Methods taken by this library are `Jbuilder#json` and any valid route helpers defined by your app e.g. `Jbuilder#post_url`. If you have or need any fields with keys like `"json"` or `"post_url"` use `Jbuilder#set!`, e.g.
166
- ```ruby
167
- json.set! 'json', 'some value'
168
- json.set! 'post_url', 'some url'
169
173
  ```
170
174
 
171
175
 
@@ -183,4 +187,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/msimon
183
187
  ## License
184
188
 
185
189
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
186
-
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module Jpartial
6
+ module Generators
7
+ # Generate a configuration template for partials.
8
+ class JpartialGenerator < Rails::Generators::Base
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ def copy_config_file
12
+ template 'jpartial.rb.erb', 'config/initializers/jpartial.rb'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ <%= "# frozen_string_literal: true" %>
2
+
3
+ <%= "Jbuilder::Jpartial.configure do |jpartial|" %>
4
+ <%= "# jpartial._post do |post|" %>
5
+ <%= "# json.post_url post_url(post)" %>
6
+ <%= "# json.title post.title" %>
7
+ <%= "# json.author_name post.author.name" %>
8
+ <%= "# end" %>
9
+ <%= "end" %>
10
+
11
+ <%= "# In `app/views/posts/show.jbuilder`" %>
12
+ <%= "# json._post @post" %>
13
+ <%= "#" %>
14
+ <%= "# Result:" %>
15
+ <%= "# {" %>
16
+ <%= "# \"post_url\": \"http://www.app.com/posts/12345\"," %>
17
+ <%= "# \"title\": \"The Number One Post\"," %>
18
+ <%= "# \"author\": \"M. Simon Borg\"" %>
19
+ <%= "# }" %>
@@ -3,25 +3,6 @@ require 'jbuilder/jpartial/version'
3
3
 
4
4
  # Top level Jbuilder class
5
5
  class Jbuilder
6
- def json
7
- self
8
- end
9
-
10
- alias_method :old_method_missing, :method_missing
11
-
12
- def method_missing(method_name, *args, &block)
13
- if _method_is_a_route_helper?(method_name)
14
- @context.send(method_name, *args, &block)
15
- else
16
- old_method_missing(method_name, *args, &block)
17
- end
18
- end
19
-
20
- def _method_is_a_route_helper?(method_name)
21
- method_name.to_s =~ /(.*)_(url|path)/ && !@context.nil? &&
22
- @context.respond_to?(method_name)
23
- end
24
-
25
6
  # Jpartial module
26
7
  module Jpartial
27
8
  DangerousMethodName = Class.new(ArgumentError)
@@ -29,18 +10,22 @@ class Jbuilder
29
10
  @defined_by_user = []
30
11
 
31
12
  def self.jpartial(name, &block)
32
- if dangerous_method_name?(name)
33
- raise DangerousMethodName, "The method `##{name}` is already defined"\
34
- ' by Jbuilder. Please choose another name to define your partial'
35
- else
36
- Jbuilder.class_eval do
37
- define_method(name, &block)
13
+ _raise_dangerous_method_name_error(name) if _dangerous_method_name?(name)
14
+ JbuilderProxy.class_eval { define_method(name, &block) }
15
+ Jbuilder.class_eval do
16
+ define_method(name) do |*args|
17
+ JbuilderProxy.new(self, @context).__send__(name, *args)
38
18
  end
39
- @defined_by_user << name unless @defined_by_user.include?(name)
40
19
  end
20
+ @defined_by_user << name unless @defined_by_user.include?(name)
41
21
  end
42
22
 
43
- def self.dangerous_method_name?(name)
23
+ def self._raise_dangerous_method_name_error(name)
24
+ raise DangerousMethodName, "The method `##{name}` is already defined"\
25
+ ' by Jbuilder. Please choose another name to define your partial'
26
+ end
27
+
28
+ def self._dangerous_method_name?(name)
44
29
  !@defined_by_user.include?(name) &&
45
30
  Jbuilder.method_defined?(name) ||
46
31
  Jbuilder.private_method_defined?(name)
@@ -58,12 +43,41 @@ class Jbuilder
58
43
  require 'active_support/basic_object'
59
44
  ActiveSupport::BasicObject
60
45
  end) do
61
-
62
46
  def method_missing(name, *args, &block)
63
47
  name = name.to_s == 'send' ? args.first.to_sym : name
64
48
  Jpartial.jpartial(name, &block)
65
49
  end
66
50
  end
51
+
52
+ # Partial method execution is defined here. Jbuilder only knows how to
53
+ # initialize an instance of the proxy class and send it the right message.
54
+ # The proxy is initialized with the execution context if there is any
55
+ # so it can pass along context methods when they're defined.
56
+ class JbuilderProxy
57
+ instance_methods.each do |meth|
58
+ next if [:method_missing, :__send__, :object_id].include?(meth)
59
+ undef_method(meth)
60
+ end
61
+
62
+ attr_reader :json
63
+
64
+ def initialize(json, context = nil)
65
+ @json = json
66
+ @context = context
67
+ end
68
+
69
+ def method_missing(method_name, *args, &block)
70
+ if _method_defined_in_context?(method_name)
71
+ @context.send(method_name, *args, &block)
72
+ else
73
+ super(method_name, *args, &block)
74
+ end
75
+ end
76
+
77
+ def _method_defined_in_context?(method_name)
78
+ !@context.nil? && @context.respond_to?(method_name)
79
+ end
80
+ end
67
81
  end
68
82
  end
69
83
 
@@ -6,6 +6,6 @@ end
6
6
 
7
7
  class Jbuilder
8
8
  module Jpartial
9
- VERSION = '1.0.2'.freeze
9
+ VERSION = '1.1.0'.freeze
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jbuilder-jpartial
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - M. Simon Borg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-11 00:00:00.000000000 Z
11
+ date: 2017-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jbuilder
@@ -59,8 +59,11 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - CHANGELOG.md
62
63
  - LICENSE.txt
63
64
  - README.md
65
+ - lib/generators/jpartial_generator.rb
66
+ - lib/generators/templates/jpartial.rb.erb
64
67
  - lib/jbuilder/jpartial.rb
65
68
  - lib/jbuilder/jpartial/railtie.rb
66
69
  - lib/jbuilder/jpartial/version.rb