pbbuilder 0.3.0 → 0.8.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 +4 -4
- data/.github/workflows/test.yml +22 -0
- data/.gitignore +1 -0
- data/README.md +2 -1
- data/lib/pbbuilder.rb +30 -10
- data/lib/pbbuilder/handler.rb +4 -2
- data/lib/pbbuilder/protobuf_extension.rb +7 -0
- data/lib/pbbuilder/template.rb +97 -0
- data/pbbuilder.gemspec +1 -1
- data/test/pbbuilder_template_test.rb +107 -0
- data/test/pbbuilder_test.rb +18 -3
- data/test/protobuf_extension_test.rb +18 -0
- data/test/test_helper.rb +21 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e22f13cb28a04d0b767c619b7c63c91e86a246d524abc200e5062d92cadb977e
|
4
|
+
data.tar.gz: b323e88b227263bfbd4ebc8b0e50f05208afe24527a2069e1110a6a605e453cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c245be23b0283a134b1dc28b1ab29d96bd9ca0023456f9e984ff3406b164f057147ab9e366bdcf150236fe494417ef182480cc1d89a53880c684403efb60bb95
|
7
|
+
data.tar.gz: e4c4bbd500f921b0b2a71a7fc0e23ec99ea005a872f7f0d66a72f04cca712de54ef3e4898023bf22880eedb9afe990d9fac54dfce62ae164fd4c0b267bfc03bb
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: ruby
|
2
|
+
on: push
|
3
|
+
|
4
|
+
jobs:
|
5
|
+
test:
|
6
|
+
runs-on: ubuntu-latest
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
ruby: ["2.7", "3.0.1"]
|
10
|
+
name: tests for ruby-${{ matrix.ruby }}
|
11
|
+
steps:
|
12
|
+
- name: Checkout code
|
13
|
+
uses: actions/checkout@v2
|
14
|
+
|
15
|
+
- name: Setup Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
bundler-cache: true
|
19
|
+
ruby-version: ${{ matrix.ruby }}
|
20
|
+
|
21
|
+
- name: Run tests
|
22
|
+
run: bin/test
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -22,7 +22,8 @@ $ gem install pbbuilder
|
|
22
22
|
```
|
23
23
|
|
24
24
|
## Contributing
|
25
|
-
|
25
|
+
|
26
|
+
When debugging, make sure you're prepending `::Kernel` to any calls such as `puts` as otherwise the code will think you're trying to add another attribute onto the protobuf.
|
26
27
|
|
27
28
|
## License
|
28
29
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/pbbuilder.rb
CHANGED
@@ -28,8 +28,8 @@ class Pbbuilder < BasicObject
|
|
28
28
|
yield self if ::Kernel.block_given?
|
29
29
|
end
|
30
30
|
|
31
|
-
def method_missing(
|
32
|
-
set!(
|
31
|
+
def method_missing(...)
|
32
|
+
set!(...)
|
33
33
|
end
|
34
34
|
|
35
35
|
def respond_to_missing?(field)
|
@@ -39,24 +39,43 @@ class Pbbuilder < BasicObject
|
|
39
39
|
def set!(field, *args, &block)
|
40
40
|
name = field.to_s
|
41
41
|
descriptor = @message.class.descriptor.lookup(name)
|
42
|
+
::Kernel.raise ::ArgumentError, "Unknown field #{name}" if descriptor.nil?
|
42
43
|
|
43
44
|
if block
|
44
|
-
raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
|
45
|
+
::Kernel.raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
|
45
46
|
|
46
47
|
if descriptor.label == :repeated
|
47
|
-
# pb.field @array { |element| pb.name
|
48
|
-
raise ::ArgumentError, "wrong number of arguments (expected 1)" unless args.length == 1
|
48
|
+
# pb.field @array { |element| pb.name element.name }
|
49
|
+
::Kernel.raise ::ArgumentError, "wrong number of arguments #{args.length} (expected 1)" unless args.length == 1
|
49
50
|
collection = args.first
|
50
51
|
_append_repeated(name, descriptor, collection, &block)
|
51
52
|
return
|
52
53
|
end
|
53
54
|
|
54
|
-
raise ::ArgumentError, "wrong number of arguments (expected 0)" unless args.empty?
|
55
|
-
# pb.field { pb.name
|
55
|
+
::Kernel.raise ::ArgumentError, "wrong number of arguments (expected 0)" unless args.empty?
|
56
|
+
# pb.field { pb.name "hello" }
|
56
57
|
message = (@message[name] ||= _new_message_from_descriptor(descriptor))
|
57
58
|
_scope(message, &block)
|
58
59
|
elsif args.length == 1
|
59
|
-
|
60
|
+
arg = args.first
|
61
|
+
if descriptor.label == :repeated
|
62
|
+
if arg.respond_to?(:to_hash)
|
63
|
+
# pb.fields {"one" => "two"}
|
64
|
+
arg.to_hash.each do |k, v|
|
65
|
+
@message[name][k] = v
|
66
|
+
end
|
67
|
+
elsif arg.respond_to?(:to_ary)
|
68
|
+
# pb.fields ["one", "two"]
|
69
|
+
# Using concat so it behaves the same as _append_repeated
|
70
|
+
@message[name].concat arg.to_ary
|
71
|
+
else
|
72
|
+
# pb.fields "one"
|
73
|
+
@message[name].push arg
|
74
|
+
end
|
75
|
+
else
|
76
|
+
# pb.field "value"
|
77
|
+
@message[name] = arg
|
78
|
+
end
|
60
79
|
else
|
61
80
|
# pb.field @value, :id, :name, :url
|
62
81
|
element = args.shift
|
@@ -89,7 +108,7 @@ class Pbbuilder < BasicObject
|
|
89
108
|
private
|
90
109
|
|
91
110
|
def _append_repeated(name, descriptor, collection, &block)
|
92
|
-
raise ::ArgumentError, "expected Enumerable" unless collection.respond_to?(:map)
|
111
|
+
::Kernel.raise ::ArgumentError, "expected Enumerable" unless collection.respond_to?(:map)
|
93
112
|
elements = collection.map do |element|
|
94
113
|
message = _new_message_from_descriptor(descriptor)
|
95
114
|
_scope(message) { block.call(element) }
|
@@ -108,7 +127,7 @@ class Pbbuilder < BasicObject
|
|
108
127
|
end
|
109
128
|
|
110
129
|
def _new_message_from_descriptor(descriptor)
|
111
|
-
raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
|
130
|
+
::Kernel.raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message
|
112
131
|
|
113
132
|
# Here we're using Protobuf reflection to create an instance of the message class
|
114
133
|
message_descriptor = descriptor.subtype
|
@@ -117,4 +136,5 @@ class Pbbuilder < BasicObject
|
|
117
136
|
end
|
118
137
|
end
|
119
138
|
|
139
|
+
require "pbbuilder/protobuf_extension"
|
120
140
|
require "pbbuilder/railtie" if defined?(Rails)
|
data/lib/pbbuilder/handler.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "pbbuilder/template"
|
2
|
+
|
1
3
|
# Basically copied and pasted from JbuilderHandler, except it uses Pbbuilder
|
2
4
|
|
3
5
|
class PbbuilderHandler
|
@@ -6,7 +8,7 @@ class PbbuilderHandler
|
|
6
8
|
def self.call(template, source = nil)
|
7
9
|
source ||= template.source
|
8
10
|
# We need to keep `source` on the first line, so line numbers are correct if there's an error
|
9
|
-
%{pb
|
10
|
-
pb.target!}
|
11
|
+
%{__already_defined = defined?(pb); pb ||= PbbuilderTemplate.new(self, @_response_class.new); #{source}
|
12
|
+
pb.target! unless (__already_defined && __already_defined != "method")}
|
11
13
|
end
|
12
14
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# PbbuilderTemplate is an extension of Pbbuilder to be used as a Rails template
|
2
|
+
# It adds support for partials.
|
3
|
+
class PbbuilderTemplate < Pbbuilder
|
4
|
+
class << self
|
5
|
+
attr_accessor :template_lookup_options
|
6
|
+
end
|
7
|
+
|
8
|
+
self.template_lookup_options = {handlers: [:pbbuilder]}
|
9
|
+
|
10
|
+
def initialize(context, message)
|
11
|
+
@context = context
|
12
|
+
super(message)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Render a partial. Can be called as:
|
16
|
+
# pb.partial! "name/of_partial", argument: 123
|
17
|
+
# pb.partial! "name/of_partial", locals: {argument: 123}
|
18
|
+
# pb.partial! partial: "name/of_partial", argument: 123
|
19
|
+
# pb.partial! partial: "name/of_partial", locals: {argument: 123}
|
20
|
+
# pb.partial! @model # @model is an ActiveModel value, it will use the name to look up a partial
|
21
|
+
def partial!(*args)
|
22
|
+
if args.one? && _is_active_model?(args.first)
|
23
|
+
_render_active_model_partial args.first
|
24
|
+
else
|
25
|
+
_render_explicit_partial(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def set!(field, *args, **kwargs, &block)
|
30
|
+
# If partial options are being passed, we render a submessage with a partial
|
31
|
+
if kwargs.has_key?(:partial)
|
32
|
+
if args.one? && kwargs.has_key?(:as)
|
33
|
+
# pb.friends @friends, partial: "friend", as: :friend
|
34
|
+
# Call set! on the super class, passing in a block that renders a partial for every element
|
35
|
+
super(field, *args) do |element|
|
36
|
+
_set_inline_partial(element, kwargs)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
# pb.best_friend partial: "person", person: @best_friend
|
40
|
+
# Call set! as a submessage, passing in the kwargs as partial options
|
41
|
+
super(field, *args) do
|
42
|
+
_render_partial_with_options(kwargs)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def _is_active_model?(object)
|
53
|
+
object.class.respond_to?(:model_name) && object.respond_to?(:to_partial_path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def _render_explicit_partial(name_or_options, locals = {})
|
57
|
+
case name_or_options
|
58
|
+
when ::Hash
|
59
|
+
# partial! partial: 'name', foo: 'bar'
|
60
|
+
options = name_or_options
|
61
|
+
else
|
62
|
+
# partial! 'name', locals: {foo: 'bar'}
|
63
|
+
options = if locals.one? && (locals.keys.first == :locals)
|
64
|
+
locals.merge(partial: name_or_options)
|
65
|
+
else
|
66
|
+
{partial: name_or_options, locals: locals}
|
67
|
+
end
|
68
|
+
# partial! 'name', foo: 'bar'
|
69
|
+
as = locals.delete(:as)
|
70
|
+
options[:as] = as if as.present?
|
71
|
+
options[:collection] = locals[:collection] if locals.key?(:collection)
|
72
|
+
end
|
73
|
+
|
74
|
+
_render_partial_with_options options
|
75
|
+
end
|
76
|
+
|
77
|
+
def _render_active_model_partial(object)
|
78
|
+
@context.render object, pb: self
|
79
|
+
end
|
80
|
+
|
81
|
+
def _set_inline_partial(object, options)
|
82
|
+
locals = ::Hash[options[:as], object]
|
83
|
+
_render_partial_with_options options.merge(locals: locals)
|
84
|
+
end
|
85
|
+
|
86
|
+
def _render_partial_with_options(options)
|
87
|
+
options.reverse_merge! locals: options.except(:partial, :as, :collection)
|
88
|
+
options.reverse_merge! ::PbbuilderTemplate.template_lookup_options
|
89
|
+
|
90
|
+
_render_partial options
|
91
|
+
end
|
92
|
+
|
93
|
+
def _render_partial(options)
|
94
|
+
options[:locals][:pb] = self
|
95
|
+
@context.render options
|
96
|
+
end
|
97
|
+
end
|
data/pbbuilder.gemspec
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "action_view/testing/resolvers"
|
3
|
+
|
4
|
+
class PbbuilderTemplateTest < ActiveSupport::TestCase
|
5
|
+
PERSON_PARTIAL = <<-PBBUILDER
|
6
|
+
pb.extract! person, :name
|
7
|
+
PBBUILDER
|
8
|
+
|
9
|
+
RACER_PARTIAL = <<-PBBUILDER
|
10
|
+
pb.extract! racer, :name
|
11
|
+
pb.friends racer.friends, partial: "racers/racer", as: :racer
|
12
|
+
pb.best_friend partial: "racers/racer", racer: racer.best_friend if racer.best_friend.present?
|
13
|
+
PBBUILDER
|
14
|
+
|
15
|
+
PARTIALS = {
|
16
|
+
"_partial.pb.pbbuilder" => "pb.name name",
|
17
|
+
"_person.pb.pbbuilder" => PERSON_PARTIAL,
|
18
|
+
"racers/_racer.pb.pbbuilder" => RACER_PARTIAL,
|
19
|
+
|
20
|
+
# Ensure we find only Pbbuilder partials from within Pbbuilder templates.
|
21
|
+
"_person.html.erb" => "Hello world!"
|
22
|
+
}
|
23
|
+
|
24
|
+
test "basic template" do
|
25
|
+
result = render('pb.name "hello"')
|
26
|
+
assert_equal "hello", result.name
|
27
|
+
end
|
28
|
+
|
29
|
+
test "partial by name with top-level locals" do
|
30
|
+
result = render('pb.partial! "partial", name: "hello"')
|
31
|
+
assert_equal "hello", result.name
|
32
|
+
end
|
33
|
+
|
34
|
+
test "submessage partial" do
|
35
|
+
other_racer = Racer.new(2, "Max Verstappen", [])
|
36
|
+
racer = Racer.new(123, "Chris Harris", [], other_racer)
|
37
|
+
result = render('pb.best_friend partial: "person", person: @racer.best_friend', racer: racer)
|
38
|
+
assert_equal "Max Verstappen", result.best_friend.name
|
39
|
+
end
|
40
|
+
|
41
|
+
test "hash" do
|
42
|
+
result = render('pb.favourite_foods "pizza" => "yes"')
|
43
|
+
assert_equal({"pizza" => "yes"}, result.favourite_foods.to_h)
|
44
|
+
end
|
45
|
+
|
46
|
+
test "partial by name with nested locals" do
|
47
|
+
result = render('pb.partial! "partial", locals: { name: "hello" }')
|
48
|
+
assert_equal "hello", result.name
|
49
|
+
end
|
50
|
+
|
51
|
+
test "partial by options containing nested locals" do
|
52
|
+
result = render('pb.partial! partial: "partial", locals: { name: "hello" }')
|
53
|
+
assert_equal "hello", result.name
|
54
|
+
end
|
55
|
+
|
56
|
+
test "partial by options containing top-level locals" do
|
57
|
+
result = render('pb.partial! partial: "partial", name: "hello"')
|
58
|
+
assert_equal "hello", result.name
|
59
|
+
end
|
60
|
+
|
61
|
+
test "partial for Active Model" do
|
62
|
+
result = render("pb.partial! @racer", racer: Racer.new(123, "Chris Harris", []))
|
63
|
+
assert_equal "Chris Harris", result.name
|
64
|
+
end
|
65
|
+
|
66
|
+
test "collection partial" do
|
67
|
+
friends = [Racer.new(1, "Johnny Test", []), Racer.new(2, "Max Verstappen", [])]
|
68
|
+
result = render("pb.partial! @racer", racer: Racer.new(123, "Chris Harris", friends))
|
69
|
+
assert_equal 2, result.friends.size
|
70
|
+
assert_equal "Johnny Test", result.friends[0].name
|
71
|
+
assert_equal "Max Verstappen", result.friends[1].name
|
72
|
+
end
|
73
|
+
|
74
|
+
test "nested message partial" do
|
75
|
+
other_racer = Racer.new(2, "Max Verstappen", [])
|
76
|
+
result = render("pb.partial! @racer", racer: Racer.new(123, "Chris Harris", [], other_racer))
|
77
|
+
assert_equal "Max Verstappen", result.best_friend.name
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def render(*args)
|
83
|
+
render_without_parsing(*args)
|
84
|
+
end
|
85
|
+
|
86
|
+
def render_without_parsing(source, assigns = {})
|
87
|
+
view = build_view(fixtures: PARTIALS.merge("source.pb.pbbuilder" => source), assigns: assigns)
|
88
|
+
view.render(template: "source", handlers: [:pbbuilder], formats: [:pb])
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_view(options = {})
|
92
|
+
resolver = ActionView::FixtureResolver.new(options.fetch(:fixtures))
|
93
|
+
lookup_context = ActionView::LookupContext.new([resolver], {}, [""])
|
94
|
+
controller = ActionView::TestCase::TestController.new
|
95
|
+
|
96
|
+
assigns = options.fetch(:assigns, {})
|
97
|
+
assigns.reverse_merge! _response_class: API::Person
|
98
|
+
|
99
|
+
view = ActionView::Base.with_empty_template_cache.new(lookup_context, assigns, controller)
|
100
|
+
|
101
|
+
def view.view_cache_dependencies
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
|
105
|
+
view
|
106
|
+
end
|
107
|
+
end
|
data/test/pbbuilder_test.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "test_helper"
|
2
|
-
require "pbbuilder"
|
3
2
|
|
4
3
|
class PbbuilderTest < ActiveSupport::TestCase
|
5
4
|
test "it makes it possible to create a person" do
|
@@ -8,9 +7,25 @@ class PbbuilderTest < ActiveSupport::TestCase
|
|
8
7
|
pb.friends 1..3 do |number|
|
9
8
|
pb.name "Friend ##{number}"
|
10
9
|
end
|
10
|
+
pb.best_friend do
|
11
|
+
pb.name "Manuelo"
|
12
|
+
end
|
13
|
+
pb.field_mask do
|
14
|
+
pb.paths ["ok", "that's"]
|
15
|
+
pb.paths "cool"
|
16
|
+
end
|
17
|
+
pb.favourite_foods({
|
18
|
+
"Breakfast" => "Eggs",
|
19
|
+
"Lunch" => "Shawarma",
|
20
|
+
"Dinner" => "Pizza"
|
21
|
+
})
|
11
22
|
end.target!
|
12
|
-
|
13
|
-
assert_equal person.
|
23
|
+
|
24
|
+
assert_equal "Hello world", person.name
|
25
|
+
assert_equal "Friend #1", person.friends.first.name
|
26
|
+
assert_equal ["ok", "that's", "cool"], person.field_mask.paths
|
27
|
+
assert_equal "Manuelo", person.best_friend.name
|
28
|
+
assert_equal "Eggs", person.favourite_foods["Breakfast"]
|
14
29
|
end
|
15
30
|
|
16
31
|
test "it can extract fields in a nice way" do
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ProtobufExtensionTest < ActiveSupport::TestCase
|
4
|
+
test ".build" do
|
5
|
+
person = API::Person.build(name: "Hello world!") do |pb|
|
6
|
+
pb.best_friend do
|
7
|
+
pb.name "Johnny"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
assert_equal "Hello world!", person.name
|
11
|
+
assert_equal "Johnny", person.best_friend.name
|
12
|
+
end
|
13
|
+
|
14
|
+
test ".build without block" do
|
15
|
+
person = API::Person.build
|
16
|
+
assert_equal "", person.name
|
17
|
+
end
|
18
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -5,9 +5,20 @@ require "rails"
|
|
5
5
|
require "rails/test_help"
|
6
6
|
require "rails/test_unit/reporter"
|
7
7
|
|
8
|
+
require "active_support"
|
9
|
+
require "active_support/core_ext/array/access"
|
10
|
+
require "active_support/cache/memory_store"
|
11
|
+
require "active_support/json"
|
12
|
+
require "active_model"
|
13
|
+
require "action_view"
|
14
|
+
require "rails/version"
|
15
|
+
|
16
|
+
require "pbbuilder"
|
17
|
+
|
8
18
|
Rails::TestUnitReporter.executable = "bin/test"
|
9
19
|
|
10
20
|
require "google/protobuf"
|
21
|
+
require "google/protobuf/field_mask_pb"
|
11
22
|
|
12
23
|
Google::Protobuf::DescriptorPool.generated_pool.build do
|
13
24
|
add_file("pbbuilder.proto", syntax: :proto3) do
|
@@ -15,6 +26,9 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
15
26
|
optional :name, :string, 1
|
16
27
|
repeated :friends, :message, 2, "pbbuildertest.Person"
|
17
28
|
optional :best_friend, :message, 3, "pbbuildertest.Person"
|
29
|
+
repeated :nicknames, :string, 4
|
30
|
+
optional :field_mask, :message, 5, "google.protobuf.FieldMask"
|
31
|
+
map :favourite_foods, :string, :string, 6
|
18
32
|
end
|
19
33
|
end
|
20
34
|
end
|
@@ -22,3 +36,10 @@ end
|
|
22
36
|
module API
|
23
37
|
Person = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pbbuildertest.Person").msgclass
|
24
38
|
end
|
39
|
+
|
40
|
+
class Racer < Struct.new(:id, :name, :friends, :best_friend)
|
41
|
+
extend ActiveModel::Naming
|
42
|
+
include ActiveModel::Conversion
|
43
|
+
end
|
44
|
+
|
45
|
+
ActionView::Template.register_template_handler :pbbuilder, PbbuilderHandler
|
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.
|
4
|
+
version: 0.8.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: 2021-
|
11
|
+
date: 2021-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -31,6 +31,7 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- ".github/workflows/test.yml"
|
34
35
|
- ".gitignore"
|
35
36
|
- Gemfile
|
36
37
|
- MIT-LICENSE
|
@@ -39,10 +40,14 @@ files:
|
|
39
40
|
- bin/test
|
40
41
|
- lib/pbbuilder.rb
|
41
42
|
- lib/pbbuilder/handler.rb
|
43
|
+
- lib/pbbuilder/protobuf_extension.rb
|
42
44
|
- lib/pbbuilder/railtie.rb
|
45
|
+
- lib/pbbuilder/template.rb
|
43
46
|
- lib/tasks/pbbuilder_tasks.rake
|
44
47
|
- pbbuilder.gemspec
|
48
|
+
- test/pbbuilder_template_test.rb
|
45
49
|
- test/pbbuilder_test.rb
|
50
|
+
- test/protobuf_extension_test.rb
|
46
51
|
- test/test_helper.rb
|
47
52
|
homepage: https://github.com/cheddar-me/pbbuilder
|
48
53
|
licenses:
|
@@ -68,5 +73,7 @@ signing_key:
|
|
68
73
|
specification_version: 4
|
69
74
|
summary: Generate Protobuf messages via a Builder-style DSL
|
70
75
|
test_files:
|
76
|
+
- test/pbbuilder_template_test.rb
|
71
77
|
- test/pbbuilder_test.rb
|
78
|
+
- test/protobuf_extension_test.rb
|
72
79
|
- test/test_helper.rb
|