From 5261b3c11101bfdd10fa8458642aaab2cf83518d Mon Sep 17 00:00:00 2001 From: Mikolai Fajer Date: Sat, 11 Oct 2014 10:48:24 -0500 Subject: [PATCH 1/4] Adding a nested version of Message.to_hash. --- lib/beefcake.rb | 10 +++++++++- test/message_test.rb | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/beefcake.rb b/lib/beefcake.rb index 2083778..22707b5 100644 --- a/lib/beefcake.rb +++ b/lib/beefcake.rb @@ -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 diff --git a/test/message_test.rb b/test/message_test.rb index 295c11e..53b8aed 100644 --- a/test/message_test.rb +++ b/test/message_test.rb @@ -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 From 940cc8dd709187bacd7f5d2040fef7be12ee7e87 Mon Sep 17 00:00:00 2001 From: Mikolai Fajer Date: Sat, 11 Oct 2014 11:06:53 -0500 Subject: [PATCH 2/4] Adding package namespace creation (also enforces CamelCase as opposed to pull request #56). --- lib/beefcake/generator.rb | 4 +++- test/generator_test.rb | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/beefcake/generator.rb b/lib/beefcake/generator.rb index 9e2ff29..56ca9d5 100644 --- a/lib/beefcake/generator.rb +++ b/lib/beefcake/generator.rb @@ -239,7 +239,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 @@ -273,6 +273,8 @@ 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.enum_type).each do |et| enum!(et) diff --git a/test/generator_test.rb b/test/generator_test.rb index ecccd53..7371784 100644 --- a/test/generator_test.rb +++ b/test/generator_test.rb @@ -33,6 +33,13 @@ 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 + + # 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 From 2902c8986dc2b8407bc044d5e5e4d090a798c7e3 Mon Sep 17 00:00:00 2001 From: Mikolai Fajer Date: Sat, 11 Oct 2014 13:47:20 -0500 Subject: [PATCH 3/4] Adding support for import/dependency. --- dat/code_generator_request_import.dat | 5 +++++ lib/beefcake/generator.rb | 10 ++++++++-- test/generator_test.rb | 9 +++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 dat/code_generator_request_import.dat diff --git a/dat/code_generator_request_import.dat b/dat/code_generator_request_import.dat new file mode 100644 index 0000000..10d6f62 --- /dev/null +++ b/dat/code_generator_request_import.dat @@ -0,0 +1,5 @@ + +bookshelf.protozb +bookshelf.proto importingaddressbook.proto"1 + BookShelf$ +books ( 2.tutorial.AddressBook \ No newline at end of file diff --git a/lib/beefcake/generator.rb b/lib/beefcake/generator.rb index 56ca9d5..9fabb45 100644 --- a/lib/beefcake/generator.rb +++ b/lib/beefcake/generator.rb @@ -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 @@ -276,6 +278,10 @@ def compile(ns, file) # 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 diff --git a/test/generator_test.rb b/test/generator_test.rb index 7371784..7786123 100644 --- a/test/generator_test.rb +++ b/test/generator_test.rb @@ -39,6 +39,15 @@ def test_generate_package_namespace 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 # Covers the regression of encoding a CodeGeneratorResponse under 1.9.2-p136 raising # Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and US-ASCII From deab19ff6205906768ea4499b057c1845bf94d3e Mon Sep 17 00:00:00 2001 From: Mikolai Fajer Date: Sat, 11 Oct 2014 13:52:26 -0500 Subject: [PATCH 4/4] Retaining directory structure from the original protobuf files. --- lib/beefcake/generator.rb | 3 ++- test/generator_test.rb | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/beefcake/generator.rb b/lib/beefcake/generator.rb index 9fabb45..c370adb 100644 --- a/lib/beefcake/generator.rb +++ b/lib/beefcake/generator.rb @@ -148,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 diff --git a/test/generator_test.rb b/test/generator_test.rb index 7786123..553fe87 100644 --- a/test/generator_test.rb +++ b/test/generator_test.rb @@ -49,6 +49,12 @@ def test_generate_import 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