Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dat/code_generator_request_import.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

bookshelf.protozb
bookshelf.proto importingaddressbook.proto"1
BookShelf$
books ( 2.tutorial.AddressBook
10 changes: 9 additions & 1 deletion lib/beefcake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,15 @@ def to_hash
__beefcake_fields__.values.inject({}) do |h, fld|
value = self[fld.name]
unless value.nil?
h[fld.name] = value
case value
when Array
next if value.empty?
h[fld.name] = value.map {|val| val.is_a?(Message) ? val.to_hash : val}
when Message
h[fld.name] = value.to_hash
else
h[fld.name] = value
end
end
h
end
Expand Down
17 changes: 13 additions & 4 deletions lib/beefcake/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ class FileDescriptorProto
optional :name, :string, 1 # file name, relative to root of source tree
optional :package, :string, 2 # e.g. "foo", "foo.bar", etc.

repeated :message_type, DescriptorProto, 4;
repeated :enum_type, EnumDescriptorProto, 5;
repeated :dependency, :string, 3

repeated :message_type, DescriptorProto, 4
repeated :enum_type, EnumDescriptorProto, 5
end


Expand Down Expand Up @@ -146,8 +148,9 @@ def self.compile(ns, req)
g.compile(ns, file)

g.c.rewind
# Change the filename to be relative to -I
CodeGeneratorResponse::File.new(
:name => File.basename(file.name, ".proto") + ".pb.rb",
:name => file.name.gsub(".proto", ".pb.rb"),
:content => g.c.read
)
end
Expand Down Expand Up @@ -239,7 +242,7 @@ def field!(pkg, f)
end
t = t.gsub(/^\.*/, "") # Remove leading `.`s

t.gsub(".", "::") # Convert to Ruby namespacing syntax
t.split(".").map { |e| e[0].capitalize + e[1..-1] }.join("::") # Convert to Ruby namespacing syntax
else
":#{name_for(f, T, f.type)}"
end
Expand Down Expand Up @@ -273,7 +276,13 @@ def compile(ns, file)
puts "require \"beefcake\""
puts

# Use the package as a namespace, converting under_scores to CamelCase for better Ruby style
ns += (file.package || "").split(/\W+/).map{ |e| e.split('_').map(&:capitalize).join('') }
ns!(ns) do
Array(file.dependency).each do |df|
puts "require \"#{df.gsub(".proto", ".pb")}\""
end

Array(file.enum_type).each do |et|
enum!(et)
end
Expand Down
22 changes: 22 additions & 0 deletions test/generator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ def test_generate_two_level_namespace
assert_match(/module Top\s*\n\s*module Bottom/m, @res.file.first.content)
end

def test_generate_package_namespace
@req.proto_file.first.package = "middle.bottom_level"
@res = Beefcake::Generator.compile(["Top"], @req)
assert_match(/module Top\s*\n\s*module Middle\s*\n\s*module BottomLevel/m, @res.file.first.content)
end

def test_generate_import
# Load up the generator request for the addressbook.proto example
dat = File.dirname(__FILE__) + "/../dat/code_generator_request_import.dat"
mock_request = File.read(dat)
@req = CodeGeneratorRequest.decode(mock_request)
@res = Beefcake::Generator.compile([], @req)
assert_equal(CodeGeneratorResponse, @res.class)
assert_match(/require "addressbook.pb"/m, @res.file.first.content)
end

def test_generate_retain_path
@req.proto_file.first.name = "proto/addressbook.proto"
@res = Beefcake::Generator.compile([], @req)
assert_equal("proto/addressbook.pb.rb", @res.file.first.name)
end

# Covers the regression of encoding a CodeGeneratorResponse under 1.9.2-p136 raising
# Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and US-ASCII
def test_encode_decode_generated_response
Expand Down
6 changes: 6 additions & 0 deletions test/message_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,12 @@ def test_bool_to_hash
assert_equal false_expectation, false_message.to_hash
end

def test_nested_to_hash
msg = CompositeMessage.new(:encodable => SimpleMessage.new(:a => 1))
exp = { :encodable => { :a => 1 } }
assert_equal(exp, msg.to_hash)
end

def test_fields_named_fields
contents = %w{fields named fields}
msg = FieldsMessage.new fields: contents
Expand Down