|
Tutorials
Brief instruction how to use this library
See also: http://code.google.com/apis/protocolbuffers/docs/tutorials.html Table of Contents
InstallThe gem is registered to a gem server, so that all you should do to install is to execute the following command: sudo gem install ruby_protobuf Compile Your .proto Filerprotoc PROTOFILE When PROTOFILE is named 'person.proto,' the name of the generated ruby source is 'person.rb.' If you want to customize the name, use -o option. rprotoc person.proto -o my_person.rb To know about other options, use -h option. rprotoc -h Generated Ruby CodeA .proto file like this: package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
extensions 100 to 200;
}
extend Person {
optional int32 age = 100;
}
message AddressBook {
repeated Person person = 1;
}generates ruby code like this: module Tutorial
class Person < ::Protobuf::Message
required :string, :name, 1
required :int32, :id, 2
optional :string, :email, 3
class PhoneType < ::Protobuf::Enum
MOBILE = 0
HOME = 1
WORK = 2
end
class PhoneNumber < ::Protobuf::Message
required :string, :number, 1
optional :PhoneType, :type, 2, {:default => :HOME}
end
repeated :PhoneNumber, :phone, 4
extensions 100..200
end
class Person < ::Protobuf::Message
optional :int32, :age, 100, :extension => true
end
class AddressBook < ::Protobuf::Message
repeated :Person, :person, 1
end
endThe Protocol Buffer APIAs you can see in the previous section, messages and fields in a proto file is respectively converted to ruby classes derived from Protobuf::Message class and their attributes. Using the class and its instance, you could write: require 'addressbook.pb' include Tutorial person = Person.new person.id = 1234 person.name = 'John Doe' person.email = 'jdoe@example.com' phone = Person::PhoneNumber.new phone.number = '555-4321' phone.type = Person::PhoneType::HOME person.phone << phone Note that the type of variable is checked in accordance with the proto file when assigned: person.no_such_field = 1 # raises NoMethodError person.id = '1234' # raises TypeError EnumsEnums are expanded into a set of symbolic constants with integer values. So, for example, the constant Tutorial::Person::PhoneType::WORK has the value 2. Standard Message Methods
Parsing and SerializationFinally, each protocol buffer class has methods for writing and reading messages of your chosen type using the protocol buffer binary format. These include:
Sample (Mini) ApplicationsWriting A Message#!/usr/local/bin/ruby
require 'addressbook.pb'
def prompt_for_address(person)
print 'Enter person ID number: '
person.id = STDIN.gets.strip.to_i
print 'Enter name: '
person.name = STDIN.gets.strip
print 'Enter email address (blank for none): '
email = STDIN.gets.strip
person.email = email unless email.empty?
loop do
print 'Enter a phone number (or leave blank to finish): '
break if (number = STDIN.gets.strip).empty?
person.phone << Tutorial::Person::PhoneNumber.new
person.phone.last.number = number
print 'Is this a mobile, home, or work phone? '
person.phone.last.type =
case type = STDIN.gets.strip
when 'mobile'
Tutorial::Person::PhoneType::MOBILE
when 'home'
Tutorial::Person::PhoneType::HOME
when 'work'
Tutorial::Person::PhoneType::WORK
else
puts 'Unknown phone type; leaving as default value.'
nil
end
end
end
unless ARGV.size == 1
puts "Usage: #{$0} ADDRESS_BOOK_FILE"
exit
end
address_book = Tutorial::AddressBook.new
address_book.parse_from_file ARGV[0] if File.exist? ARGV[0]
address_book.person << Tutorial::Person.new
prompt_for_address address_book.person.last
address_book.serialize_to_file ARGV[0]Reading A Message#!/usr/local/bin/ruby
require 'addressbook.pb'
def list_people(address_book)
address_book.person.each do |person|
puts "Person ID: #{person.id}"
puts " Name: #{person.name}"
puts " E-mail: #{person.email}" unless person.email.empty?
person.phone.each do |phone_number|
print(case phone_number.type
when Tutorial::Person::PhoneType::MOBILE
' Mobile phone #: '
when Tutorial::Person::PhoneType::HOME
' Home phone #: '
when Tutorial::Person::PhoneType::WORK
' Work phone #: '
end)
puts phone_number.number
end
end
end
unless ARGV.size == 1
puts "Usage: #{$0} ADDRESS_BOOK_FILE"
exit
end
address_book = Tutorial::AddressBook.new
address_book.parse_from_file ARGV[0]
list_people address_book
|
Sign in to add a comment
I can successfully run the 'write' code the first time. When it tries to read from the file I just created, it blows up. Any idea what is causing this? I also tried manually creating an address book object (from the 'The Protocol Buffer API' section above) and it blew up the same way in the parse_from_file call.
gems/ruby_protobuf-0.3.0/lib/protobuf/message/field.rb:579:in `pack': pack(U): value out of range (RangeError?)
I get the same thing.
Does anyone know if this project is still being maintained?
Comments are not notified. I read these comment just now. I'm grad if you add an issue when you find a bug.
To pauljsolomon and snow.gregory,
How about 0.3.2? On my computer, it looks work.
I have done a comparison of reading 1 million json message and transform it into a protobuf object. That's about 5.5 times slower than reading the same 1 million json message, convert it to ruby hash, then convert the hash back to json message and output to file.
The json-to-ruby-to-json-plus-io is in theory doing more. The json-to-protobuf doesn't output the serialized stream yet. All it does is construct the protobuf data object.