pbbuilder 0.18.0 → 0.19.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: 75cb2682f8933e0e8acb2b3bb6a525df5447dab8a65b2d8509f54a3c2b430c35
4
- data.tar.gz: '0282cfeb404460224fd8cb2d32d134335b9d307d2edefc4af854368b9c8788e1'
3
+ metadata.gz: 1ea3598ad1ed31172d0b3154c6968649f63073f23de0d94abf191a07dbdbf4e0
4
+ data.tar.gz: 7285883ae069eeff4f1860eb9b4c4a727585e6762b3bfd974ce1fb9e51928086
5
5
  SHA512:
6
- metadata.gz: d429891ca19333b9e626ccd9bf63462fbe61eea672c8ac14f427aafdc392a2f12e36370e63f1a4522c384b4375e81433d63d804f447d508346744aedca448fbf
7
- data.tar.gz: 1af6634160780c84f93a99d9b6b282e90500da24d654bfa36f1220b48260bec074412da69f83267a2df8f935e33218b332a27cf102765e6eff7b3db853ec686e
6
+ metadata.gz: e051d79882379fb30f3f0b4bab503e6591034d1cc16639918d685a0ef19e6f7cc42ea224954bf755db739f6a2b2c2c86a8c7666e23065ce337aafb862486b4f6
7
+ data.tar.gz: 90f2266161a9a101fd4b67afb71130a009b17ec9a5139dc583db18d02a1a32a2bd7730f1ea872c3d4b77a4d64f953b1a34e72cb35f845dc6a879f117f7c3c5ec
@@ -14,21 +14,12 @@ jobs:
14
14
  fail-fast: false
15
15
  matrix:
16
16
  ruby: ["3.0", "3.1", "3.2", "3.3"]
17
-
18
- gemfile: [ "rails_6_1", "rails_7_0"]
17
+ gemfile: [ "rails_6_1", "rails_7_0", "rails_7_2"]
18
+ exclude:
19
+ - ruby: "3.0"
20
+ gemfile: "rails_7_2"
19
21
  experimental: [false]
20
22
 
21
- #include:
22
- # - ruby: '2.7'
23
- # gemfile: rails_head
24
- # experimental: true
25
- # - ruby: '3.0'
26
- # gemfile: rails_head
27
- # experimental: true
28
- # - ruby: '3.1'
29
- # gemfile: rails_head
30
- # experimental: true
31
-
32
23
  steps:
33
24
  - uses: actions/checkout@v3
34
25
 
data/Appraisals CHANGED
@@ -6,6 +6,6 @@ appraise "rails-7-0" do
6
6
  gem "rails", "~> 7.0.0"
7
7
  end
8
8
 
9
- appraise "rails-7-1" do
10
- gem "rails", "~> 7.1.0"
11
- end
9
+ appraise "rails-7-2" do
10
+ gem "rails", "~> 7.2.0"
11
+ end
data/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## 0.19.0
7
+ ### Added
8
+ - Add support for rails 7.2, but leave out rails 7.1 support. This is because ActionView has a breaking bug in 7.1 that renders the template back as a string
9
+ instead of an object, like we need for Pbbuilder https://github.com/rails/rails/pull/51023
10
+
11
+ ## 0.18.0
12
+ ### Added
13
+ - Allow literal assignment of protos to fields
14
+
6
15
  ## 0.17.0
7
16
  ### Changed
8
17
  - Instead of appending to repeated enum message, we're replacing it to avoid issues in case output will be rendered twice
data/Gemfile CHANGED
@@ -7,5 +7,3 @@ gemspec
7
7
 
8
8
  gem "rake"
9
9
  gem "appraisal"
10
-
11
- gem "ruby-lsp"
data/README.md CHANGED
@@ -1,22 +1,19 @@
1
1
  # Pbbuilder
2
- PBBuilder generates [Protobuf](https://developers.google.com/protocol-buffers) Messages with a simple DSL similar to [JBuilder](https://rubygems.org/gems/jbuilder) gem.
2
+ PBBuilder generates [Protobuf](https://developers.google.com/protocol-buffers) Messages with a simple DSL similar to the [JBuilder](https://rubygems.org/gems/jbuilder) gem.
3
3
 
4
4
 
5
- At least Rails 6.1 is required.
6
-
7
- > [!WARNING]
8
- > There currently is a regression in ActionView (the part of Rails which renders) that forces rendered objects into strings. This is only present
9
- > in Rails 7.1, and is fixed in Rails. However, a 7.1 gem containing the fix hasn't been released yet. For the moment you should refrain
10
- > from using pbbuilder and rails-twirp with Rails 7.1 and wait for the next version to be released.
5
+ At least Rails 6.1 is required and rails 7.1 is currently not supported.
6
+ There currently is a regression in ActionView (the part of Rails which renders) that forces rendered objects into strings, but for Pbbuilder we need the raw objects.
7
+ This is only present in Rails 7.1, and a fix is released in Rails 7.2. https://github.com/rails/rails/pull/51023
11
8
 
12
9
  ## Compatibility with jBuilder
13
10
  We don't aim to have 100% compitability and coverage with jbuilder gem, but we closely follow jbuilder's API design to maintain familiarity.
14
11
 
15
12
  | | Jbuilder | Pbbuilder |
16
13
  |---|---|---|
17
- | set! | ✅ | ✅ |
18
- | cache! | ✅ | ✅ |
19
- | cache_if! | ✅ | ✅ |
14
+ | set! | ✅ | ✅ |
15
+ | cache! | ✅ | ✅ |
16
+ | cache_if! | ✅ | ✅ |
20
17
  | cache_root! | ✅| |
21
18
  | fragment cache | ✅| ✅ |
22
19
  | extract! | ✅ | ✅ |
@@ -25,7 +22,7 @@ We don't aim to have 100% compitability and coverage with jbuilder gem, but we c
25
22
  | array! | ✅ | |
26
23
  | .call | ✅ | |
27
24
 
28
- Due to protobuf message implementation, there is absolutely no need to implement support for `deep_format_keys!`, `key_format!`, `key_format`, `deep_format_keys`, `ignore_nil!`, `ignore_nil!`, `nil`. So those would never be added.
25
+ Due to the protobuf message implementation, there is absolutely no need to implement support for `deep_format_keys!`, `key_format!`, `key_format`, `deep_format_keys`, `ignore_nil!`, `ignore_nil!`, `nil`. So those would never be added.
29
26
 
30
27
  ## Usage
31
28
  The main difference is that it can use introspection to figure out what kind of protobuf message it needs to create.
@@ -61,7 +58,7 @@ pb.phone_number account.phone_number
61
58
  pb.tag account.tag
62
59
  ```
63
60
 
64
- could be rewritten to a shorter version with a use of `extract!`.
61
+ can be rewritten to a shorter version with the use of `extract!`.
65
62
  ```
66
63
  pb.extract! account, :id, :phone_number, :tag
67
64
  ```
@@ -80,7 +77,7 @@ Using partial while passing a variable to it
80
77
  pb.account partial: "account", account: @account
81
78
  ```
82
79
 
83
- Here is way to use partials with collection while passing a variable to it
80
+ Here is a way to use partials with a collection while passing a variable to it
84
81
 
85
82
  ```
86
83
  pb.accounts @accounts, partial: "account", as: account
@@ -96,7 +93,7 @@ pb.friends partial: "racers/racer", as: :racer, collection: @racers
96
93
  pb.friends "racers/racer", as: :racer, collection: @racers
97
94
  ```
98
95
 
99
- And there are other ways, that don't use Collection Renderer (not very effective probably)
96
+ And there are other ways, that don't use CollectionRenderer
100
97
  ```ruby
101
98
  pb.partial! @racer, racer: Racer.new(123, "Chris Harris", friends)
102
99
  ```
@@ -105,7 +102,7 @@ pb.friends @friends, partial: "racers/racer", as: :racer
105
102
  ```
106
103
 
107
104
  ### Caching
108
- it uses Rails.cache and works like caching in HTML templates:
105
+ It uses Rails.cache and works like caching in HTML templates:
109
106
 
110
107
  ```
111
108
  pb.cache! "cache-key", expires_in: 10.minutes do
@@ -121,7 +118,7 @@ pb.cache_if! !admin?, "cache-key", expires_in: 10.minutes do
121
118
  end
122
119
  ```
123
120
 
124
- Fragment caching currently works through ActionView::CollectionRenderer and can be used only with the following syntax:
121
+ Fragment caching currently works through ActionView::CollectionRenderer and can only be used with the following syntax:
125
122
 
126
123
  ```ruby
127
124
  pb.friends partial: "racers/racer", as: :racer, collection: @racers, cached: true
@@ -151,10 +148,14 @@ $ gem install pbbuilder
151
148
 
152
149
  When debugging, make sure to prepend `::Kernel` to any calls such as `puts` as otherwise the code will think you're trying to add another attribute into protobuf object.
153
150
 
154
- In case, you're looking to use breakpoints for debugging purposes - it's better to use `pry`. Just make sure to [change pbbuilder superclass from `ProxyObject/BasicObject` to `Object`](lib/pbbuilder/pbbuilder.rb).
151
+ In case you're looking to use breakpoints (for debugging purposes via `binding.pry` for instance), let Pbbuilder inherit from `Object` instead of `BasicObject`]
152
+ Seen in:
153
+ [Pbbuilder](lib/pbbuilder/pbbuilder.rb)
154
+ [Errors](lib/pbbuilder/errors.rb)
155
155
 
156
156
  ## Testing
157
- Running `bundle exec appraisal rake test` locally will run entire testsuit with all version of rails. To run tests only for certain rails version do the following `bundle exec appraisal rails-7-0 rake test`
157
+ Running `bundle exec appraisal rake test` locally will run the entire testsuit with all versions of rails.
158
+ To run tests only for a certain rails version do the following `bundle exec appraisal rails-7-0 rake test`
158
159
 
159
160
  To run only one tests from file - use `m` utility. Like this:
160
161
  `bundle exec appraisal rails-7-0 m test/pbbuilder_template_test.rb:182`
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/setup"
4
3
  require "bundler/gem_tasks"
5
4
  require "rake/testtask"
6
5
 
@@ -11,10 +10,28 @@ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["CI"]
11
10
  else
12
11
  Rake::TestTask.new(:test) do |t|
13
12
  t.libs << "test"
14
- t.pattern = "test/**/*_test.rb"
15
- t.verbose = false
16
- t.warning = false
13
+ t.libs << "lib"
14
+
15
+ # Running specific tests with line numbers, like with rails test, is not supported by default in rake.
16
+ # By setting the TESTOPS env var we can however specify the name of a single test with underscores instead of spaces.
17
+ # So run your single test by calling for ex:
18
+ #
19
+ # rake test /Users/sebastian/projects/cheddar/rails-twirp/test/ping_controller_test.rb "uncaught errors should bubble up to the test"
20
+
21
+ file_name = ARGV[1]
22
+ test_name = ARGV[2]&.tr(" ", "_")
23
+
24
+ ENV["TESTOPTS"] = "--verbose"
25
+
26
+ t.test_files = if file_name
27
+ if test_name
28
+ ENV["TESTOPTS"] += " --name=test_#{test_name}"
29
+ end
30
+ [file_name]
31
+ else
32
+ FileList["test/**/*_test.rb"]
33
+ end
17
34
  end
18
35
 
19
36
  task default: :test
20
- end
37
+ end
@@ -4,7 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rake"
6
6
  gem "appraisal"
7
- gem "ruby-lsp"
8
7
  gem "rails", "~> 6.1.0"
9
8
 
10
9
  gemspec path: "../"
@@ -4,7 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rake"
6
6
  gem "appraisal"
7
- gem "ruby-lsp"
8
7
  gem "rails", "~> 7.0.0"
9
8
 
10
9
  gemspec path: "../"
@@ -4,7 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "rake"
6
6
  gem "appraisal"
7
- gem "ruby-lsp"
8
- gem "rails", "~> 7.1.0"
7
+ gem "rails", "~> 7.2.0"
9
8
 
10
9
  gemspec path: "../"
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pbbuilder'
4
-
5
- class Pbbuilder
3
+ class Pbbuilder < BasicObject
6
4
  class MergeError < ::StandardError
7
5
  def self.build(current_value, updates)
8
6
  message = "Can't merge #{updates.inspect} into #{current_value.inspect}"
9
7
  self.new(message)
10
8
  end
11
9
  end
12
- end
10
+ end
@@ -17,6 +17,7 @@ class PbbuilderTemplate < Pbbuilder
17
17
  end
18
18
 
19
19
  # Render a partial. Can be called as:
20
+ #
20
21
  # pb.partial! "name/of_partial", argument: 123
21
22
  # pb.partial! "name/of_partial", locals: {argument: 123}
22
23
  # pb.partial! partial: "name/of_partial", argument: 123
@@ -30,7 +31,7 @@ class PbbuilderTemplate < Pbbuilder
30
31
  end
31
32
  end
32
33
 
33
- # Set the value in the message field.
34
+ # Sets the value in the message field.
34
35
  #
35
36
  # @example
36
37
  # pb.friends @friends, partial: "friend", as: :friend
@@ -39,31 +40,30 @@ class PbbuilderTemplate < Pbbuilder
39
40
  # pb.friends "racers/racer", as: :racer, collection: [Racer.new(1, "Johnny Test", []), Racer.new(2, "Max Verstappen", [])]
40
41
 
41
42
  def set!(field, *args, **kwargs, &block)
42
- # If partial options are being passed, we render a submessage with a partial
43
+ # If any partial options are being passed, we render a submessage with a partial
43
44
  if kwargs.has_key?(:partial)
44
45
  if args.one? && kwargs.has_key?(:as)
45
- # example syntax that should end up here:
46
+ # Example syntax that should end up here:
46
47
  # pb.friends @friends, partial: "friend", as: :friend
47
48
  # Call set! on the super class, passing in a block that renders a partial for every element
48
49
  super(field, *args) do |element|
49
50
  _set_inline_partial(element, kwargs)
50
51
  end
51
52
  elsif kwargs.has_key?(:collection) && kwargs.has_key?(:as)
52
- # example syntax that should end up here:
53
+ # Example syntax that should end up here:
53
54
  # pb.friends partial: "racers/racer", as: :racer, collection: [Racer.new(1, "Johnny Test", []), Racer.new(2, "Max Verstappen", [])]
54
55
 
55
56
  _render_collection_with_options(field, kwargs[:collection], kwargs)
56
57
  else
57
- # # example syntax that should end up here:
58
+ # Example syntax that should end up here:
58
59
  # pb.best_friend partial: "person", person: @best_friend
59
-
60
60
  super(field, *args) do
61
61
  _render_partial_with_options(kwargs)
62
62
  end
63
63
  end
64
64
  else
65
65
  if args.one? && kwargs.has_key?(:collection) && kwargs.has_key?(:as)
66
- # example syntax that should end up here:
66
+ # Example syntax that should end up here:
67
67
  # pb.friends "racers/racer", as: :racer, collection: [Racer.new(1, "Johnny Test", []), Racer.new(2, "Max Verstappen", [])]
68
68
  _render_collection_with_options(field, kwargs[:collection], kwargs.merge(partial: args.first))
69
69
  else
@@ -72,7 +72,7 @@ class PbbuilderTemplate < Pbbuilder
72
72
  end
73
73
  end
74
74
 
75
- # Caches fragment of message. Can be called like the following:
75
+ # Caches a fragment of a message with a given cache key. Can be called like the following:
76
76
  # 'pb.cache! "cache-key" do; end'
77
77
  # 'pb.cache! "cache-key", expire_in: 1.min do; end'
78
78
  #
@@ -107,16 +107,16 @@ class PbbuilderTemplate < Pbbuilder
107
107
 
108
108
  private
109
109
 
110
- # Uses ActionView::CollectionRenderer to render collection effectively and to use rails built in fragment caching support.
110
+ # Uses ActionView::CollectionRenderer to render the collection effectively and to use rails' built-in fragment caching support.
111
111
  #
112
- # The way recursive rendering works is that the CollectionRenderer needs to be aware of the node its currently rendering and parent node.
113
- # There is no need to know the entire "stack" of nodes. ActionView::CollectionRenderer would traverse to bottom node render it first and then go one leve up in stack,
114
- # rince and repeat until entire stack is rendered.
112
+ # The way recursive rendering works is that the CollectionRenderer needs to be aware of the node it's currently rendering and it's parent node.
113
+ # There is no need to know the entire "stack" of nodes. ActionView::CollectionRenderer will traverse to the bottom node, render it first and then go one level up in the stack.
114
+ # Rinse and repeat until the entire stack is rendered.
115
115
 
116
116
  # CollectionRenderer uses locals[:pb] to render the partial as a protobuf message,
117
117
  # but also needs locals[:pb_parent] to apply the rendered partial to the top level protobuf message.
118
118
 
119
- # This logic can be found in CollectionRenderer#build_rendered_collection method that we overwrote.
119
+ # This logic can be found in the CollectionRenderer#build_rendered_collection method that we overwrote.
120
120
  def _render_collection_with_options(field, collection, options)
121
121
  partial = options[:partial]
122
122
 
@@ -128,15 +128,15 @@ class PbbuilderTemplate < Pbbuilder
128
128
  options[:locals].merge!(field: field)
129
129
 
130
130
  if options.has_key?(:layout)
131
- raise ::NotImplementedError, "The `:layout' option is not supported in collection rendering."
131
+ ::Kernel.raise ::NotImplementedError, "The `:layout' option is not supported in collection rendering."
132
132
  end
133
133
 
134
134
  if options.has_key?(:spacer_template)
135
- raise ::NotImplementedError, "The `:spacer_template' option is not supported in collection rendering."
135
+ ::Kernel.raise ::NotImplementedError, "The `:spacer_template' option is not supported in collection rendering."
136
136
  end
137
137
 
138
138
  CollectionRenderer
139
- .new(@context.lookup_context, options) { |&block| _scope(message[field.to_s],&block) }
139
+ .new(@context.lookup_context, options) { |&block| _scope(message[field.to_s], &block) }
140
140
  .render_collection_with_partial(collection, partial, @context, nil)
141
141
  end
142
142
 
@@ -172,10 +172,9 @@ class PbbuilderTemplate < Pbbuilder
172
172
  begin
173
173
  ::Rails.cache.write(key, value, options)
174
174
  rescue ::SystemCallError
175
- # In case ActiveSupport::Cache::FileStore in Rails is used as a cache,
176
- # File.atomic_write can have a race condition and fail to rename temporary
177
- # file. We're attempting to recover from that, by catching this specific
178
- # error and returning a value.
175
+ # In case `ActiveSupport::Cache::FileStore` in Rails is used as a cache,
176
+ # `File.atomic_write` can have a race condition and fails to rename temporary file.
177
+ # We're attempting to recover from that by catching this specific error and returning a value.
179
178
  #
180
179
  # @see https://github.com/rails/rails/pull/44151
181
180
  # @see https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/file/atomic.rb#L50
data/lib/pbbuilder.rb CHANGED
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pbbuilder/pbbuilder"
4
- require 'pbbuilder/errors'
3
+ require "pbbuilder/errors"
5
4
  require "pbbuilder/protobuf_extension"
6
5
  require "pbbuilder/railtie" if defined?(Rails)
7
6
 
8
-
9
- # Pbbuilder makes it easy to create a protobuf message using the builder pattern
7
+ # Pbbuilder makes it easy to create a protobuf message using the builder pattern.
10
8
  # It is heavily inspired by jbuilder
11
9
  #
12
10
  # Given this example message definition:
@@ -15,8 +13,10 @@ require "pbbuilder/railtie" if defined?(Rails)
15
13
  # repeated Person friends = 2;
16
14
  # }
17
15
  #
18
- # You could use Pbbuilder as follows:
16
+ # You can use Pbbuilder as follows:
17
+ #
19
18
  # person = RPC::Person.new
19
+ #
20
20
  # Pbbuilder.new(person) do |pb|
21
21
  # pb.name "Hello"
22
22
  # pb.friends [1, 2, 3] do |number|
@@ -29,7 +29,7 @@ require "pbbuilder/railtie" if defined?(Rails)
29
29
  # It basically works exactly like jbuilder. The main difference is that it can use introspection to figure out what kind
30
30
  # of protobuf message it needs to create.
31
31
 
32
- class Pbbuilder
32
+ class Pbbuilder < BasicObject
33
33
  def initialize(message)
34
34
  @message = message
35
35
 
@@ -48,11 +48,15 @@ class Pbbuilder
48
48
  !!_descriptor_for_field(field)
49
49
  end
50
50
 
51
+ # When calling for ex: response.drivers, where response is a Google::Protobuf object, 'drivers' is not a method on that. These
52
+ # methods (or messages in our case) get added here. This is of course based on what kind of message it is. Singular, an array
53
+ # (repeated) etc. with their arguments.
51
54
  def set!(field, *args, &block)
52
55
  name = field.to_s
53
56
  descriptor = _descriptor_for_field(name)
54
- ::Kernel.raise ::ArgumentError, "Unknown field #{name}" if descriptor.nil?
57
+ ::Kernel.raise ::ArgumentError, "Unknown field: #{name}" if descriptor.nil?
55
58
 
59
+ # An block is used to pass on it's children
56
60
  if ::Kernel.block_given?
57
61
  ::Kernel.raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
58
62
 
@@ -66,9 +70,11 @@ class Pbbuilder
66
70
  # example syntax that should end up here:
67
71
  # pb.field { pb.name "hello" }
68
72
  ::Kernel.raise ::ArgumentError, "wrong number of arguments (expected 0)" unless args.empty?
73
+
69
74
  message = (@message[name] ||= _new_message_from_descriptor(descriptor))
70
75
  _scope(message, &block)
71
76
  end
77
+ # No block given, but with 1 argument
72
78
  elsif args.length == 1
73
79
  arg = args.first
74
80
  if descriptor.label == :repeated
@@ -106,7 +112,7 @@ class Pbbuilder
106
112
  else
107
113
  # example syntax that should end up here:
108
114
  # pb.field "value"
109
-
115
+
110
116
  @message[name] = arg
111
117
  end
112
118
  else
@@ -128,6 +134,8 @@ class Pbbuilder
128
134
  end
129
135
  end
130
136
 
137
+ # Shorthand command for getting a few attributes from an object.
138
+ # pb.extract! racer, :name, :id, :age
131
139
  def extract!(element, *args)
132
140
  args.each { |arg| @message[arg.to_s] = element.send(arg) }
133
141
  end
@@ -181,6 +189,7 @@ class Pbbuilder
181
189
  @message
182
190
  end
183
191
 
192
+ # @param field string
184
193
  def new_message_for(field)
185
194
  descriptor = _descriptor_for_field(field)
186
195
  ::Kernel.raise ::ArgumentError, "Unknown field #{field}" if descriptor.nil?
@@ -190,11 +199,14 @@ class Pbbuilder
190
199
 
191
200
  private
192
201
 
202
+ # Lookup the field name (or 'attribute' name, for ex "best_friend") on the Google descriptor (Google::Protobuf::Descriptor) of our
203
+ # message object.
204
+ # @param field string
193
205
  def _descriptor_for_field(field)
194
206
  @message.class.descriptor.lookup(field.to_s)
195
207
  end
196
208
 
197
- # Appends protobuf message with existing @message object
209
+ # Appends protobuf objects to our 'repeated' attribute. This can create a list of items to a repeated field.
198
210
  #
199
211
  # @param name string
200
212
  # @param descriptor Google::Protobuf::FieldDescriptor
@@ -210,7 +222,8 @@ class Pbbuilder
210
222
  @message[name].push(*elements)
211
223
  end
212
224
 
213
- # Yields an Protobuf object in a scope of message and provided values.
225
+ # Yields a Protobuf object in the scope of message and provided values.
226
+ # This will 'assign' the field values as it were to the message attributes.
214
227
  #
215
228
  # @param message Google::Protobuf::(field_type)
216
229
  def _scope(message)
@@ -222,7 +235,7 @@ class Pbbuilder
222
235
  @message = old_message
223
236
  end
224
237
 
225
- # Build up empty protobuf message based on descriptor
238
+ # Builds up an empty protobuf message based on the given descriptor.
226
239
  #
227
240
  # @param descriptor Google::Protobuf::FieldDescriptor
228
241
  def _new_message_from_descriptor(descriptor)
data/pbbuilder.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "pbbuilder"
5
- spec.version = "0.18.0"
5
+ spec.version = "0.19.0"
6
6
  spec.authors = ["Bouke van der Bijl"]
7
7
  spec.email = ["bouke@cheddar.me"]
8
8
  spec.homepage = "https://github.com/cheddar-me/pbbuilder"
@@ -57,7 +57,7 @@ class PbbuilderTemplateTest < ActiveSupport::TestCase
57
57
  test "collection partial with fragment caching enabled" do
58
58
  template = <<-PBBUILDER
59
59
  racers = [Racer.new(1, "Johnny Test", [], nil, API::Asset.new(url: "https://google.com/test1.svg")), Racer.new(2, "Max Verstappen", [])]
60
- pb.friends partial: "racers/racer", as: :racer, collection: racers, cached: true
60
+ pb.friends partial: "racers/racer", collection: racers, cached: true, as: :racer
61
61
  PBBUILDER
62
62
  result = render(template)
63
63
 
@@ -83,7 +83,7 @@ class PbbuilderTemplateTest < ActiveSupport::TestCase
83
83
  end
84
84
 
85
85
  test "render collections with partial as arg" do
86
- skip("This will be addressed in future version of a gem")
86
+ skip("This will be addressed in a future version of this gem")
87
87
  result = render('pb.friends "racers/racer", as: :racer, collection: [Racer.new(1, "Johnny Test", []), Racer.new(2, "Max Verstappen", [])]')
88
88
 
89
89
  assert_equal 2, result.friends.count
@@ -62,7 +62,7 @@ class PbbuilderTest < ActiveSupport::TestCase
62
62
 
63
63
  assert_equal(["ok", "that's"], p.field_mask.paths)
64
64
  end
65
-
65
+
66
66
  test "sets the last value of the repeated field to be the only value" do
67
67
  person = Pbbuilder.new(API::Person.new) do |pb|
68
68
  pb.field_mask do
data/test/test_helper.rb CHANGED
@@ -55,10 +55,16 @@ class << Rails
55
55
  end
56
56
  end
57
57
 
58
+ Pbbuilder::CollectionRenderer.collection_cache = Rails.cache
59
+
58
60
  class Racer < Struct.new(:id, :name, :friends, :best_friend, :logo)
59
61
  extend ActiveModel::Naming
60
62
  include ActiveModel::Conversion
61
63
 
64
+ def cache_key
65
+ "racer-#{id}"
66
+ end
67
+
62
68
  # Fragment caching needs to know, if record could be persisted. We set it to false, this is a default in ActiveModel::API.
63
69
  def persisted?
64
70
  false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pbbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bouke van der Bijl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-25 00:00:00.000000000 Z
11
+ date: 2024-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -89,13 +89,12 @@ files:
89
89
  - gemfiles/rails_6_1.gemfile
90
90
  - gemfiles/rails_7.gemfile
91
91
  - gemfiles/rails_7_0.gemfile
92
- - gemfiles/rails_7_1.gemfile
92
+ - gemfiles/rails_7_2.gemfile
93
93
  - gemfiles/rails_head.gemfile
94
94
  - lib/pbbuilder.rb
95
95
  - lib/pbbuilder/collection_renderer.rb
96
96
  - lib/pbbuilder/errors.rb
97
97
  - lib/pbbuilder/handler.rb
98
- - lib/pbbuilder/pbbuilder.rb
99
98
  - lib/pbbuilder/protobuf_extension.rb
100
99
  - lib/pbbuilder/railtie.rb
101
100
  - lib/pbbuilder/template.rb
@@ -123,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
122
  - !ruby/object:Gem::Version
124
123
  version: '0'
125
124
  requirements: []
126
- rubygems_version: 3.3.7
125
+ rubygems_version: 3.5.18
127
126
  signing_key:
128
127
  specification_version: 4
129
128
  summary: Generate Protobuf Messages with a simple DSL similar to JBuilder
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Pbbuilder = Class.new(begin
4
- require 'active_support/proxy_object'
5
- ActiveSupport::ProxyObject
6
- rescue LoadError
7
- require 'active_support/basic_object'
8
- ActiveSupport::BasicObject
9
- end)