Class: Pbbuilder
- Inherits:
- BasicObject
- Defined in:
- lib/pbbuilder.rb,
lib/pbbuilder/railtie.rb
Overview
Pbbuilder makes it easy to create a protobuf message using the builder pattern It is heavily inspired by jbuilder
Given this example message definition: message Person
string name = 1;
repeated Person friends = 2;
You could use Pbbuilder as follows: person = RPC::Person.new Pbbuilder.new(person) do |pb|
pb.name "Hello"
pb.friends [1, 2, 3] do |number|
pb.name "Friend ##{number}"
end
end
message.name => “Hello”
It basically works exactly like jbuilder. The main difference is that it can use introspection to figure out what kind of protobuf message it needs to create.
Direct Known Subclasses
Defined Under Namespace
Classes: Railtie
Instance Method Summary collapse
- #extract!(element, *args) ⇒ Object
-
#initialize(message) {|_self| ... } ⇒ Pbbuilder
constructor
A new instance of Pbbuilder.
- #method_missing ⇒ Object
- #respond_to_missing?(field) ⇒ Boolean
- #set!(field, *args, &block) ⇒ Object
- #target! ⇒ Object
Constructor Details
#initialize(message) {|_self| ... } ⇒ Pbbuilder
Returns a new instance of Pbbuilder.
25 26 27 28 29 |
# File 'lib/pbbuilder.rb', line 25 def initialize() @message = yield self if ::Kernel.block_given? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing ⇒ Object
31 32 33 |
# File 'lib/pbbuilder.rb', line 31 def method_missing(...) set!(...) end |
Instance Method Details
#extract!(element, *args) ⇒ Object
97 98 99 100 101 102 |
# File 'lib/pbbuilder.rb', line 97 def extract!(element, *args) args.each do |arg| value = element.send(arg) @message[arg.to_s] = value end end |
#respond_to_missing?(field) ⇒ Boolean
35 36 37 |
# File 'lib/pbbuilder.rb', line 35 def respond_to_missing?(field) !!@message.class.descriptor.lookup(field.to_s) end |
#set!(field, *args, &block) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/pbbuilder.rb', line 39 def set!(field, *args, &block) name = field.to_s descriptor = @message.class.descriptor.lookup(name) ::Kernel.raise ::ArgumentError, "Unknown field #{name}" if descriptor.nil? if block ::Kernel.raise ::ArgumentError, "can't pass block to non-message field" unless descriptor.type == :message if descriptor.label == :repeated # pb.field @array { |element| pb.name element.name } ::Kernel.raise ::ArgumentError, "wrong number of arguments #{args.length} (expected 1)" unless args.length == 1 collection = args.first _append_repeated(name, descriptor, collection, &block) return end ::Kernel.raise ::ArgumentError, "wrong number of arguments (expected 0)" unless args.empty? # pb.field { pb.name "hello" } = (@message[name] ||= (descriptor)) _scope(, &block) elsif args.length == 1 arg = args.first if descriptor.label == :repeated if arg.respond_to?(:to_hash) # pb.fields {"one" => "two"} arg.to_hash.each do |k, v| @message[name][k] = v end elsif arg.respond_to?(:to_ary) # pb.fields ["one", "two"] # Using concat so it behaves the same as _append_repeated @message[name].concat arg.to_ary else # pb.fields "one" @message[name].push arg end else # pb.field "value" @message[name] = arg end else # pb.field @value, :id, :name, :url element = args.shift if descriptor.label == :repeated # If the message field that's being assigned is a repeated field, then we assume that `element` is enumerable. # This way you can do something like pb.repeated_field @array, :id, :name # This will create a message out of every object in @array, copying over the :id and :name values. set!(name, element) do |item| extract!(item, *args) end else set!(name) do extract!(element, *args) end end end end |
#target! ⇒ Object
104 105 106 |
# File 'lib/pbbuilder.rb', line 104 def target! @message end |