Skip to content

Commit 1f72f3d

Browse files
committed
Messages fields should be able to be set with to_proto
A prior commit introduced a bug so that you would get `Failure/Error: fail TypeError, "Unacceptable value #{value} for field #{field.name} of type #{field.type_class}"` when trying to set a message field with a class that defined a #to_proto method.
1 parent 757068b commit 1f72f3d

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

lib/protobuf/field/message_field.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class MessageField < BaseField
99
#
1010

1111
def acceptable?(val)
12-
val.is_a?(type_class) || val.respond_to?(:to_hash)
12+
val.is_a?(type_class) || val.respond_to?(:to_hash) || val.respond_to?(:to_proto)
1313
end
1414

1515
def decode(bytes)
@@ -35,8 +35,8 @@ def coerce!(value)
3535
nil
3636
elsif value.is_a?(type_class)
3737
value
38-
elsif value.respond_to?(:to_proto)
39-
value.to_proto
38+
elsif value.respond_to?(:to_proto) && (proto_value = value.to_proto).is_a?(type_class)
39+
proto_value
4040
elsif value.respond_to?(:to_hash)
4141
type_class.new(value.to_hash)
4242
else
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
require 'spec_helper'
2+
3+
RSpec.describe Protobuf::Field::MessageField do
4+
class MessageField < ::Protobuf::Message
5+
optional :int32, :field, 1
6+
end
7+
8+
class SomeMessage < ::Protobuf::Message
9+
optional MessageField, :message_field, 1
10+
end
11+
12+
class ToProtoMessageField
13+
def to_proto
14+
MessageField.new(:field => 42)
15+
end
16+
end
17+
18+
class ToProtoIsForWrongMessage
19+
def to_proto
20+
SomeMessage.new()
21+
end
22+
end
23+
24+
class ToHashMessageField
25+
def to_hash
26+
{:field => 989}
27+
end
28+
end
29+
30+
let(:instance) { SomeMessage.new }
31+
32+
describe 'setting and getting field' do
33+
context "when set with the message type" do
34+
let(:value) { MessageField.new(:field => 34) }
35+
36+
it 'is readable as a message' do
37+
instance.message_field = value
38+
expect(instance.message_field).to eq(value)
39+
end
40+
end
41+
42+
context "when set with #to_proto" do
43+
let(:value) { ToProtoMessageField.new }
44+
45+
it 'is readable as a message' do
46+
instance.message_field = value
47+
expect(instance.message_field).to eq(value.to_proto)
48+
end
49+
end
50+
51+
context "when set with #to_proto that returns the wrong message type" do
52+
let(:value) { ToProtoIsForWrongMessage.new }
53+
54+
it 'fails' do
55+
expect { instance.message_field = value }.to raise_error TypeError
56+
end
57+
end
58+
59+
context "when set with #to_hash" do
60+
let(:value) { ToHashMessageField.new }
61+
62+
it 'is readable as a message' do
63+
instance.message_field = value
64+
expect(instance.message_field).to eq(MessageField.new(value.to_hash))
65+
end
66+
end
67+
end
68+
end

0 commit comments

Comments
 (0)