-
Notifications
You must be signed in to change notification settings - Fork 98
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
endWe 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
endA class that inherits from Protobuf::Enum has a very simple interface. Any defined 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 # => :ALABAMAConstant 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::ALABAMAIf you wish to programmatically access all of the defined values in an enum, you can either use .constants or .values. The .values class method returns a hash of all of the defined EnumValue values, keyed by symbol name.
Foo::States.constants # => [ :ALABAMA, :ALASKA, :ARKANSAS, ... ]
Foo::States.values.keys # => [ :ALABAMA, :ALASKA, :ARKANSAS, ... ]