-
Notifications
You must be signed in to change notification settings - Fork 101
Messages & Enums
Given the following compiled definition of a Foo::User
:
# lib/foo/user.pb.rb
module Foo
class States < ::Protobuf::Enum
define :ALABAMA, 1
#...
end
class User < ::Protobuf::Message; end
class Address < ::Protobuf::Message; end
class User
optional ::Protobuf::Field::StringField, :first_name, 1
optional ::Protobuf::Field::StringField, :last_name, 2
optional ::Foo::Address, :address, 3
end
class Address
optional ::Protobuf::Field::StringField, :street, 1
optional ::Protobuf::Field::StringField, :city, 2
optional ::Foo::States, :state, 3
optional ::Protobuf::Field::Int32, :zip_code, 4
end
We can require the .pb.rb
file and create user objects in a similar style to working with a Struct
. New objects can use dot-notation to get/set fields from the proto object. You can also instantiate new protos with a hash where keys are the field names. Any keys not corresponding to defined fields are silently discarded.
Whether using a the setter method or passing in values via hash, the value is processeed by the same code that will reject bad values. Notice in the example below that we can assign fields of a Message type either with the object of that type or a hash. If a hash is given the type is simply instantiated with that hash and assigned.
require 'lib/foo/user.pb'
# dot notation reading/writing fields
user = Foo::User.new
user.first_name = "Lloyd"
user.last_name = "Christmas"
user.first_name # => "Lloyd"
user.address = Foo::Address.new({ :street => '21 Jump Street',
:city => 'Alphaville',
:state => Foo::States::CALIFORNIA,
:zip_code => 12345 })
# or pass in the fields as a hash to the initializer (nested hashes are perfectly acceptable)
user = Foo::User.new({ :first_name => "Lloyd",
:last_name => "Christmas",
:address => { :street => '21 Jump Street',
:city => 'Alphaville',
:state => Foo::States::CALIFORNIA,
:zip_code => 12345 } })
user.first_name # => Lloyd
user.last_name # => Christmas
# lib/foo/user.pb.rb
module Foo
class States < ::Protobuf::Enum
define :ALABAMA, 1
define :ALASKA, 2
define :ARIZONA, 3
#...
end
end
A class that inherits from Protobuf::Enum
has a very simple interface. Any define
d value becomes a constant in the class' namespace. Each EnumValue
object has a name
and a value
(alternately accessed via to_i
).
# Access an EnumValue directly by the named constant
Foo::States::ALABAMA # => 1
Foo::States::ALABAMA.to_i # => 1 (preferred method)
Foo::States::ALABAMA.value # => 1 (remains for backwards compatability)
Foo::States::ALABAMA.name # => :ALABAMA
Constant access is nice if you know the name, but if you only have the value or name in a variable, use Enum.fetch
to get the corresponding EnumValue
. There are other access methods if you have an integer value or a string/symbol name, but fetch handles all those cases (and more), so use it.
user.address.state # => 1
enum_state = Foo::States.fetch(user.address.state) # => Foo::State::ALABAMA