avro_turf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9673b4898c8bc5f75fbbdd90b2f4ac3f235c8a07
4
+ data.tar.gz: 21bb1f430e089ba31e488cd813e5343c961a2325
5
+ SHA512:
6
+ metadata.gz: 377dcdbd55e9789edc4a38f8324fe0ac2a52f34f06cfdc291a499e67bc4ab6fa9069a5f7fa3a2ff4e057625a5236694832f4c55fd8491bea8558b476c641170e
7
+ data.tar.gz: 6644b4bcb1cb6b9bf4d3e1030f814897fff44a7b134ad038987b3c52e9f469686055d3416b1b4c144d69010ef3a2576d73625d45e6f366dc3030591c531accc7
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in avro_turf.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Daniel Schierbeck
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # AvroTurf
2
+
3
+ AvroTurf is a library that makes it easier to encode and decode data using the [Apache Avro](http://avro.apache.org/) serialization format. It adds a layer on top of the official Avro gem which makes it easier to integrate Avro into your application:
4
+
5
+ * Provides an idiomatic Ruby interface.
6
+ * Allows referencing schemas defined in another file.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'avro_turf'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install avro_turf
23
+
24
+ ## Usage
25
+
26
+ Using AvroTurf is quite simple:
27
+
28
+ ```ruby
29
+ # Schemas will be looked up from the specified directory.
30
+ avro = AvroTurf.new(schemas_path: "app/schemas/")
31
+
32
+ # Decode some data using a named schema. The schema file should exist in the
33
+ # schemas directory with the file name `<name>.avsc`.
34
+ avro.decode(encoded_data, schema_name: "person")
35
+
36
+ # Encode some data using the named schema.
37
+ avro.encode({ "name" => "Jane", "age" => 28 }, schema_name: "person")
38
+ ```
39
+
40
+ ### Inter-schema references
41
+
42
+ Unlike the official Avro library, AvroTurf allows schemas to reference each other. As an example:
43
+
44
+ ```json
45
+ // person.avsc
46
+ {
47
+ "name": "person",
48
+ "type": "record",
49
+ "fields": [
50
+ {
51
+ "name": "full_name",
52
+ "type": "string"
53
+ },
54
+ {
55
+ "name": "address",
56
+ "type": "address"
57
+ }
58
+ ]
59
+ }
60
+
61
+ // address.avsc
62
+ {
63
+ "name": "address",
64
+ "type": "record",
65
+ "fields": [
66
+ {
67
+ "name": "street",
68
+ "type": "string"
69
+ },
70
+ {
71
+ "name": "city",
72
+ "type": "string"
73
+ }
74
+ ]
75
+ }
76
+ ```
77
+
78
+ In the example above, the `person` schema references the `address` schema, even though the latter is defined in another file. This makes it possible to share types across schemas, e.g.
79
+
80
+ ```json
81
+ // person_list.avsc
82
+ {
83
+ "name": "person_list",
84
+ "type": "array",
85
+ "items": "person"
86
+ }
87
+ ```
88
+
89
+ There's no reason to copy-paste the `person` schema into the `person_list` schema, as you can reference it directly.
90
+
91
+ This feature helps avoid subtle errors when the same type is represented using slightly different schemas.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/avro_turf.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'avro_turf/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "avro_turf"
8
+ spec.version = AvroTurf::VERSION
9
+ spec.authors = ["Daniel Schierbeck"]
10
+ spec.email = ["dasch@zendesk.com"]
11
+ spec.summary = "A library that makes it easier to use the Avro serialization format from Ruby"
12
+ spec.homepage = "https://github.com/dasch/avro_turf"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "avro", "~> 1.7.7"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.2.0"
25
+ spec.add_development_dependency "fakefs"
26
+ end
data/lib/avro_turf.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'avro_turf/version'
2
+ require 'avro'
3
+
4
+ class AvroTurf
5
+ def initialize(schemas_path:)
6
+ @schemas_path = schemas_path
7
+ end
8
+
9
+ # Encodes data to Avro using the specified schema.
10
+ #
11
+ # data - The data that should be encoded.
12
+ # schema_name - The name of a schema in the `schemas_path`.
13
+ #
14
+ # Returns a String containing the encoded data.
15
+ def encode(data, schema_name:)
16
+ schema = resolve_schema(schema_name)
17
+ writer = Avro::IO::DatumWriter.new(schema)
18
+
19
+ io = StringIO.new
20
+ dw = Avro::DataFile::Writer.new(io, writer, schema)
21
+ dw << data
22
+ dw.close
23
+
24
+ io.string
25
+ end
26
+
27
+ # Decodes Avro data.
28
+ #
29
+ # encoded_data - A String containing Avro-encoded data.
30
+ # schema_name - The String name of the schema that should be used to read
31
+ # the data. If nil, the writer schema will be used.
32
+ #
33
+ # Returns whatever is encoded in the data.
34
+ def decode(encoded_data, schema_name: nil)
35
+ io = StringIO.new(encoded_data)
36
+ schema = schema_name && resolve_schema(schema_name)
37
+ reader = Avro::IO::DatumReader.new(nil, schema)
38
+ dr = Avro::DataFile::Reader.new(io, reader)
39
+ dr.first
40
+ end
41
+
42
+ private
43
+
44
+ # Resolves and returns a schema.
45
+ #
46
+ # schema_name - The String name of the schema to resolve.
47
+ # names - A Hash mapping schema names to Avro::Schema instances. Used
48
+ # when referencing custom types.
49
+ #
50
+ # Returns an Avro::Schema.
51
+ def resolve_schema(schema_name, names = {})
52
+ schema_path = File.join(@schemas_path, schema_name + ".avsc")
53
+ Avro::Schema.real_parse(JSON.parse(File.read(schema_path)), names)
54
+ rescue ::Avro::SchemaParseError => e
55
+ # This is a hack in order to figure out exactly which type was missing. The
56
+ # Avro gem ought to provide this data directly.
57
+ if e.to_s =~ /"(\w+)" is not a schema we know about/
58
+ resolve_schema($1, names)
59
+
60
+ # Re-resolve the original schema now that the dependency has been resolved.
61
+ names.delete(schema_name)
62
+ resolve_schema(schema_name, names)
63
+ else
64
+ raise
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,3 @@
1
+ class AvroTurf
2
+ VERSION = "0.0.1"
3
+ end
data/spec/avro_spec.rb ADDED
@@ -0,0 +1,128 @@
1
+ require 'fakefs/spec_helpers'
2
+
3
+ describe AvroTurf do
4
+ include FakeFS::SpecHelpers
5
+
6
+ let(:avro) { AvroTurf.new(schemas_path: "spec/schemas/") }
7
+
8
+ before do
9
+ FileUtils.mkdir_p("spec/schemas")
10
+ end
11
+
12
+ it "encodes and decodes data using a named schema" do
13
+ schema = <<-AVSC
14
+ {
15
+ "name": "person",
16
+ "type": "record",
17
+ "fields": [
18
+ {
19
+ "type": "string",
20
+ "name": "full_name"
21
+ },
22
+ {
23
+ "name": "address",
24
+ "type": {
25
+ "type": "record",
26
+ "name": "address",
27
+ "fields": [
28
+ {
29
+ "type": "string",
30
+ "name": "street"
31
+ },
32
+ {
33
+ "type": "string",
34
+ "name": "city"
35
+ }
36
+ ]
37
+ }
38
+ }
39
+ ]
40
+ }
41
+ AVSC
42
+
43
+ FileUtils.mkdir_p("spec/schemas")
44
+
45
+ File.open("spec/schemas/person.avsc", "w") do |f|
46
+ f.write(schema)
47
+ end
48
+
49
+ data = {
50
+ "full_name" => "John Doe",
51
+ "address" => {
52
+ "street" => "Market st. 989",
53
+ "city" => "San Francisco"
54
+ }
55
+ }
56
+
57
+ encoded_data = avro.encode(data, schema_name: "person")
58
+
59
+ expect(avro.decode(encoded_data, schema_name: "person")).to eq(data)
60
+ end
61
+
62
+ it "resolves named types" do
63
+ File.open("spec/schemas/person.avsc", "w") do |f|
64
+ f.write <<-AVSC
65
+ {
66
+ "name": "person",
67
+ "type": "record",
68
+ "fields": [
69
+ {
70
+ "type": "string",
71
+ "name": "full_name"
72
+ },
73
+ {
74
+ "name": "address",
75
+ "type": "address"
76
+ }
77
+ ]
78
+ }
79
+ AVSC
80
+ end
81
+
82
+ File.open("spec/schemas/address.avsc", "w") do |f|
83
+ f.write <<-AVSC
84
+ {
85
+ "type": "record",
86
+ "name": "address",
87
+ "fields": [
88
+ {
89
+ "type": "string",
90
+ "name": "street"
91
+ },
92
+ {
93
+ "type": "string",
94
+ "name": "city"
95
+ }
96
+ ]
97
+ }
98
+ AVSC
99
+ end
100
+
101
+ data = {
102
+ "full_name" => "John Doe",
103
+ "address" => {
104
+ "street" => "Market st. 989",
105
+ "city" => "San Francisco"
106
+ }
107
+ }
108
+
109
+ encoded_data = avro.encode(data, schema_name: "person")
110
+
111
+ expect(avro.decode(encoded_data, schema_name: "person")).to eq(data)
112
+ end
113
+
114
+ it "allows decoding without specifying a reader schema" do
115
+ File.open("spec/schemas/message.avsc", "w") do |f|
116
+ f.write <<-AVSC
117
+ {
118
+ "name": "message",
119
+ "type": "string"
120
+ }
121
+ AVSC
122
+ end
123
+
124
+ encoded_data = avro.encode("hello, world", schema_name: "message")
125
+
126
+ expect(avro.decode(encoded_data)).to eq "hello, world"
127
+ end
128
+ end
@@ -0,0 +1,2 @@
1
+ require 'bundler/setup'
2
+ require 'avro_turf'
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: avro_turf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Schierbeck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: avro
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.7.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.7.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.2.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakefs
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - dasch@zendesk.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - avro_turf.gemspec
97
+ - lib/avro_turf.rb
98
+ - lib/avro_turf/version.rb
99
+ - spec/avro_spec.rb
100
+ - spec/spec_helper.rb
101
+ homepage: https://github.com/dasch/avro_turf
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.2.2
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: A library that makes it easier to use the Avro serialization format from
125
+ Ruby
126
+ test_files:
127
+ - spec/avro_spec.rb
128
+ - spec/spec_helper.rb
129
+ has_rdoc: