sequel-protobuf 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +5 -0
- data/Gemfile +14 -0
- data/README.md +95 -0
- data/Rakefile +7 -0
- data/lib/sequel/plugins/protobuf.rb +195 -0
- data/lib/sequel/plugins/protobuf/drivers.rb +1 -0
- data/lib/sequel/plugins/protobuf/drivers/ruby-protocol-buffers-driver.rb +64 -0
- data/lib/sequel/plugins/protobuf/version.rb +12 -0
- data/sequel-protobuf.gemspec +16 -0
- data/test/helpers/definition_error_sequel_model.rb +6 -0
- data/test/helpers/models/test.pb.rb +34 -0
- data/test/helpers/models/test.proto +17 -0
- data/test/helpers/my_message_sequel_model.rb +8 -0
- data/test/helpers/nested_sequel_model.rb +6 -0
- data/test/sequel/plugins/protobuf/drivers/ruby_protocol_buffers_test.rb +62 -0
- data/test/sequel/plugins/protobuf_test.rb +135 -0
- data/test/test_helper.rb +32 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NTVjMDc0ODk3ZGE3Mzk5MjU3YmFjYzM2OWE2OGRmYWRlOTlmN2YzNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MmI0YmE0ODFjNTUzNDc4MWQyMzcwNjlhNGVjNGUyYWI4MjMyZDU0MA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2Q4N2Y2YzgyYmZiNDE4YTRkMjk0NGIzYzcyYzQ0MDA5YWMxOTY2ZmM3OTk4
|
10
|
+
NDQ4YjYzMmUxYjg1Mzk0YjBhMWFiOThhODY2OTZiMTM2MDI2MWIzNDBkNzhj
|
11
|
+
ZDk0OGNmZmRmY2FlMDgzOTRjM2MwMzcxNzVlMGIwOWYxYTgzZTA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OGE0MzcwMDdhMmM3MGM3ZjU1MGRkOTVhMjE0NjU3Njg2NTc3MTA3ZGYxNmQ3
|
14
|
+
MGIxYjlkM2FiZDdlMDk2ZWU1MjY3OTE5YjFhNDIzNDBkMTM4YTQ0ZTRjY2Mz
|
15
|
+
N2JlNmFjMmQ3M2VkNDQ5YjYwNTc4OTIwZjVjMGU4YTJjYjI1OGU=
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
#sequel-protobuf
|
2
|
+
[](https://drone.io/github.com/kellydunn/sequel-protobuf/latest)
|
3
|
+
|
4
|
+
##what
|
5
|
+
|
6
|
+
A plugin for the `sequel` database library that enables `Sequel::Model` classes to be serialized into protocol buffers.
|
7
|
+
|
8
|
+
##documentation
|
9
|
+
|
10
|
+
Documentation can be found [here](http://rubydoc.info/github/kellydunn/sequel-protobuf/master/frames).
|
11
|
+
|
12
|
+
##installation
|
13
|
+
|
14
|
+
There is an intent to have this gem available through rubygems eventually, but for now, it's easiest to require the gem through `bundler` by specifying it in your `Gemfile`:
|
15
|
+
|
16
|
+
**Gemfile**
|
17
|
+
```
|
18
|
+
gem 'sequel-protobuf', :git => "git@github.com/kellydunn/sequel-protobuf"
|
19
|
+
```
|
20
|
+
|
21
|
+
##usage
|
22
|
+
|
23
|
+
In your `Sequel::Model` definition, require `sequel`, `sequel-protobuf`, a protocol buffer utility library of your choice (like `ruby-protocol-buffers`), and the corresponding protocol buffer model definition (the `.pb.rb` file that `ruby-protoc` generates). Next, specify that you want your `Sequel::Model` class to use the `protobuf` plugin along with the class name of the protobuf model definition, like so:
|
24
|
+
|
25
|
+
```
|
26
|
+
require 'sequel'
|
27
|
+
require 'sequel/plugins/protobuf'
|
28
|
+
require 'protocol_buffers'
|
29
|
+
require 'your/protocol/buffer/definitions/my_model_definition'
|
30
|
+
|
31
|
+
class MyModel < Sequel::Model
|
32
|
+
plugin :protobuf, :model => MyModelDefinition
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
Now you can create a new instance of your record, and call `to_protobuf` or `from_protobuf` on it!
|
37
|
+
|
38
|
+
Simple `Sequel::Dataset` operations will also work as well!
|
39
|
+
|
40
|
+
```
|
41
|
+
5.times do
|
42
|
+
MyModel.create()
|
43
|
+
end
|
44
|
+
|
45
|
+
result = MyModel.all.to_protobuf
|
46
|
+
# result is an array of protocol buffer representations of each instance of {MyModel}!
|
47
|
+
```
|
48
|
+
|
49
|
+
##configuration
|
50
|
+
|
51
|
+
As of `0.2.0`, `sequel-protobuf` provides the ability to render nested protocol buffer models, re-format data-types on demand, and override default protocol buffer definitions while rendering. To do this, you may supply an options hash to the `to_protobuf` and `as_protobuf` methods with any of the following keys:
|
52
|
+
|
53
|
+
- `:include`: specifies nested protocol buffer models to render
|
54
|
+
- `:as`: specifies a different protocol buffer model definition in which to render the current object as
|
55
|
+
- `:coerce`: specifies how to re-format a specific data column of the current `Sequel::Model` such that it can fit your protocol buffer definition.
|
56
|
+
|
57
|
+
###Example
|
58
|
+
```
|
59
|
+
require 'sequel'
|
60
|
+
require 'sequel/plugins/protobuf'
|
61
|
+
require 'protocol_buffers'
|
62
|
+
require 'your/protocol/buffer/definitions/my_model_definition'
|
63
|
+
|
64
|
+
class MyModel < Sequel::Model
|
65
|
+
plugin :protobuf, :model => MyModelDefinition
|
66
|
+
one_to_many :nested
|
67
|
+
|
68
|
+
def app_specific_as_protobuf
|
69
|
+
config = {
|
70
|
+
:as => DifferentModelDefinition,
|
71
|
+
:include => {
|
72
|
+
:nested => {}
|
73
|
+
}
|
74
|
+
:coerce => {
|
75
|
+
# We coerce the creatd_at time since Protocol Buffers
|
76
|
+
# do not support Time types by default.
|
77
|
+
# The reccomended approach is to set the unix timestamp value
|
78
|
+
# as a int64 type.
|
79
|
+
:created_at => Proc.new { |created_at|
|
80
|
+
created_at.utc.to_i
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
return self.as_protobuf(config)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
##considerations
|
91
|
+
|
92
|
+
- This library currently only supports `ruby-protocol-buffers` as a serialization driver. If you are interested in adding additional driver support, feel free to open a Pull Request!
|
93
|
+
|
94
|
+
[](https://bitdeli.com/free "Bitdeli Badge")
|
95
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'sequel/plugins/protobuf/drivers'
|
2
|
+
|
3
|
+
# This module contains all functionality for the Sequel library.
|
4
|
+
module Sequel
|
5
|
+
|
6
|
+
# This module contains all Sequel plugin definitions.
|
7
|
+
module Plugins
|
8
|
+
|
9
|
+
# This module defines the Protobuf plugin for the Sequel database library
|
10
|
+
module Protobuf
|
11
|
+
|
12
|
+
# This error message indicates that a {Sequel::Model} definition
|
13
|
+
# that has been required by the client is missing a protobuf model definition.
|
14
|
+
class MissingProtobufDefinitionError < StandardError
|
15
|
+
|
16
|
+
# Creates a new instance of {Sequel::Plugins::Protobuf::MissingProtobufDefinitionError}
|
17
|
+
def initialize
|
18
|
+
super("Protobuf model definition was not specified.")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This constant lists all of the current compatible drivers in sequel-protobuf
|
23
|
+
DRIVERS = {
|
24
|
+
:ruby_protocol_buffers => Sequel::Plugins::Protobuf::Drivers::RubyProtocolBuffers
|
25
|
+
}
|
26
|
+
|
27
|
+
# This constant defines the default driver for sequel-protobuf
|
28
|
+
# If clients do not specify a driver, sequel-protobuf assumes they
|
29
|
+
# will use this gem.
|
30
|
+
DEFAULT_DRIVER = :ruby_protocol_buffers
|
31
|
+
|
32
|
+
# Initializes the sequel-protobuf the first time it is registered for a class.
|
33
|
+
#
|
34
|
+
# @param model {Sequel::Model}. The {Sequel::Model} in which to register the plugin.
|
35
|
+
# @param options {Hash}. A configuration hash that is used to help configure the application.
|
36
|
+
def self.apply(model, options={})
|
37
|
+
# TODO no-op
|
38
|
+
end
|
39
|
+
|
40
|
+
# Initializes the sequel-protobuf plugin for the passed in model
|
41
|
+
# with the passed in options
|
42
|
+
#
|
43
|
+
# @param model {Sequel::Model}. The {Sequel::Model} in which to register the plugin
|
44
|
+
# @param options {Hash}. A configuration hash to configure the plugin
|
45
|
+
def self.configure(model, options = {})
|
46
|
+
model.instance_eval {
|
47
|
+
if !options[:model]
|
48
|
+
raise Sequel::Plugins::Protobuf::MissingProtobufDefinitionError.new
|
49
|
+
else
|
50
|
+
@protobuf_model = options[:model]
|
51
|
+
end
|
52
|
+
|
53
|
+
driver = options[:driver] ? options[:driver] : DEFAULT_DRIVER
|
54
|
+
@protobuf_driver = DRIVERS[driver]
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# When mixed in, this module provides the ability for objects
|
59
|
+
# to be serialized from protocol buffer strings
|
60
|
+
module ClassMethods
|
61
|
+
attr_reader :protobuf_driver, :protobuf_model
|
62
|
+
|
63
|
+
# Creates and returns a new instance of the current class
|
64
|
+
# from the passed in protobuf message
|
65
|
+
#
|
66
|
+
# @param protobuf {String}. The protobuf message to parse.
|
67
|
+
# @param options {Hash}. An options hash that will configure the parsing.
|
68
|
+
def from_protobuf(protobuf, options = {})
|
69
|
+
pb_model = @protobuf_driver.parse(@protobuf_model, protobuf, options)
|
70
|
+
|
71
|
+
# Coerce data from protobuf array to a new model
|
72
|
+
model = self.send(:new)
|
73
|
+
model.columns.each do |v|
|
74
|
+
if pb_model.respond_to?("#{v}=".to_sym)
|
75
|
+
model.send("#{v}=", pb_model.send(v.to_sym))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return model
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# When mixed in, this module provides various instance-level methods that
|
84
|
+
# allow sequel models to be rendered into protocol buffers
|
85
|
+
# or rendered into a driver-specific model
|
86
|
+
module InstanceMethods
|
87
|
+
|
88
|
+
# Renders the current instance of the model to a protocol buffer message
|
89
|
+
# as it is defined in the configured protocol buffer model definition.
|
90
|
+
#
|
91
|
+
# @param options {Hash}. An options hash that is used to configure how
|
92
|
+
# the rendering is performed.
|
93
|
+
# @return {String}. A protocol buffer representation of the current {Sequel::Model} instance.
|
94
|
+
def to_protobuf(options = {})
|
95
|
+
return self.render(self, options).to_s
|
96
|
+
end
|
97
|
+
|
98
|
+
# Renders the current instance of the model to an instance of {::ProtocolBuffers::Message}.
|
99
|
+
#
|
100
|
+
# @param options {Hash}. An options hash that is used to configure how
|
101
|
+
# The rendering is performed.
|
102
|
+
# @return {Object}. A representation of the model as an instance of the protocol_buffer model class
|
103
|
+
# configured at the instance level.
|
104
|
+
def as_protobuf(options = {})
|
105
|
+
return self.render(self, options)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Renders the passed in key ans the corresponding protocol buffer model.
|
109
|
+
# The passed in options specifies how to do this with the following rules:
|
110
|
+
# - `:include` This key specifies that the current protocol buffer model has a nested
|
111
|
+
# Protocol buffer model to be rendered inside of it.
|
112
|
+
# - `:coerce` This key specifies that the current model can override a specific data
|
113
|
+
# value of a particular database column. This is useful fo re-formatting
|
114
|
+
# data from your db schema so that they adhere to your protocol
|
115
|
+
# buffer definitions.
|
116
|
+
# - `:as` This key specifies a different protocol buffer model to render the
|
117
|
+
# current object.
|
118
|
+
#
|
119
|
+
# @param current {Object}. The current seciton of the schema to render.
|
120
|
+
# @param options {Hash}. An options hash to configure how to render the current object.
|
121
|
+
def render(current, options={})
|
122
|
+
|
123
|
+
# If the current element in the schema is an array,
|
124
|
+
# then we need to render them in sequence and return the result.
|
125
|
+
if current.is_a?(Array)
|
126
|
+
collection = current.inject([]) do |acc, element|
|
127
|
+
acc << render(element, options)
|
128
|
+
acc
|
129
|
+
end
|
130
|
+
|
131
|
+
return collection
|
132
|
+
|
133
|
+
# Otherwise, if the record isn't nil,
|
134
|
+
# we get the current values of the object and process them accordingly.
|
135
|
+
elsif !current.nil?
|
136
|
+
values = current.values.dup
|
137
|
+
|
138
|
+
# If the options do not specifiy a protobuf model, assume the one configured earlier
|
139
|
+
if options.has_key?(:as)
|
140
|
+
model = options[:as]
|
141
|
+
else
|
142
|
+
model = current.class.protobuf_model
|
143
|
+
end
|
144
|
+
|
145
|
+
options.each do |k, v|
|
146
|
+
|
147
|
+
# If the current key is "include", then recursively render the model specified
|
148
|
+
if k == :include
|
149
|
+
v.each do |model, opts|
|
150
|
+
values.merge!({model => render(current.send(model.to_sym), opts)})
|
151
|
+
end
|
152
|
+
|
153
|
+
# If the current key is "coerce", then call the corresponding proc
|
154
|
+
# for the desired attribute
|
155
|
+
elsif k == :coerce
|
156
|
+
v.each do |value, proc|
|
157
|
+
values[value] = proc.call(values[value])
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Finally, return the result of creating a new protobuf model
|
163
|
+
return current.class.protobuf_driver.create(model, values)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
# When mixed in, this module provides the ability for Sequel datasets to
|
170
|
+
# call `to_protobuf`, which will return an array of serialized protobuf strings.
|
171
|
+
module DatasetMethods
|
172
|
+
|
173
|
+
# Renders the current dataset of the model into a collection of
|
174
|
+
# protocol buffer messages as they are defined in the configured
|
175
|
+
# protocol buffer model definition.
|
176
|
+
#
|
177
|
+
# @param options {Hash}. An options hash that is used to configure how
|
178
|
+
# the rendering is preformed.
|
179
|
+
# @return {Array}. An array of protocol buffer messages. Each element
|
180
|
+
# In the array is a serialized version of the corresponding
|
181
|
+
# object in the original dataset.
|
182
|
+
def to_protobuf(options = {})
|
183
|
+
|
184
|
+
res = self.all.inject([]) do |acc, obj|
|
185
|
+
acc << obj.to_protobuf(options)
|
186
|
+
acc
|
187
|
+
end
|
188
|
+
|
189
|
+
return res
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'sequel/plugins/protobuf/drivers/ruby-protocol-buffers-driver'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
module Protobuf
|
4
|
+
|
5
|
+
# This module contains all the driver definitions for the sequel-protobuf gem.
|
6
|
+
module Drivers
|
7
|
+
|
8
|
+
# This driver definition provides a standard interface
|
9
|
+
# for protocol buffer serialization with the `ruby-protocol-buffers` gem.
|
10
|
+
module RubyProtocolBuffers
|
11
|
+
|
12
|
+
# Parses the passed in protobuf message into
|
13
|
+
# an instance of the corresponding protocol buffer model definition
|
14
|
+
#
|
15
|
+
# @param protobuf_model {Object}. The class of the protocol buffer definition
|
16
|
+
# @param protobuf {String}. The protocol buffer message to be parsed
|
17
|
+
# @param options {Hash}. An options hash to help configure the parsing functionality.
|
18
|
+
def self.parse(protobuf_model, protobuf, options = {})
|
19
|
+
return protobuf_model.send(:parse, protobuf)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Serializes the passed in attributes hash into an instance of the passed in
|
23
|
+
# protocol buffer model definition.
|
24
|
+
#
|
25
|
+
# @param protobuf_model {Object}. The class of the protocol buffer definition
|
26
|
+
# @param attributes {Hash}. The attributes in which to be serialized into a protocol buffer message
|
27
|
+
# @param options {Hash}. An options hash to help configure the serialization funcitonality.
|
28
|
+
# @return {::ProtocolBuffers::Message}. A newly created protocol buffer message
|
29
|
+
def self.serialize(protobuf_model, attributes, options = {})
|
30
|
+
return self.create(protobuf_model, attributes, options).to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates and returns a new instance of the specified protobuf model
|
34
|
+
# initialized with the passed in attributes and configured by the passed in optoins.
|
35
|
+
#
|
36
|
+
# @param protobuf_model {Object}. The protobuf model in which to render.
|
37
|
+
# @param attributes {Hash}. A hash of attributes in which to create the new protobuf model
|
38
|
+
# @param options {Hash}. A configuration hash in which to configure the creation of the
|
39
|
+
# New protocol buffer object.
|
40
|
+
# @return {::ProtocolBuffers::Message}. A newly created protocol buffer message.
|
41
|
+
def self.create(protobuf_model, attributes, options = {})
|
42
|
+
fields = protobuf_model.fields.inject([]) do |acc, (k, v)|
|
43
|
+
acc << v.name
|
44
|
+
acc
|
45
|
+
end
|
46
|
+
|
47
|
+
attributes = attributes.inject({}) do |acc, (k, v)|
|
48
|
+
if fields.include?(k)
|
49
|
+
acc[k] = v
|
50
|
+
end
|
51
|
+
|
52
|
+
acc
|
53
|
+
end
|
54
|
+
|
55
|
+
return protobuf_model.send(:new, attributes)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
module Protobuf
|
4
|
+
|
5
|
+
# This constant describes the current version of the sequel-protobuf gem
|
6
|
+
# It currently makes use of the semantic-versioning specification.
|
7
|
+
# To learn more about semantic verisoning, visit http://semver.org/
|
8
|
+
VERSION="0.2.2"
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path("../lib/sequel/plugins/protobuf/version.rb", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ["kellydunn"]
|
5
|
+
gem.email = ["defaultstring+sequel-protobuf@gmail.com"]
|
6
|
+
gem.description = %q{Sequel plugin for protocol buffer serialization}
|
7
|
+
gem.summary = %q{Sequel plugin for protocol buffer serialization}
|
8
|
+
gem.homepage = 'http://github.com/kellydunn/sequel-protobuf'
|
9
|
+
|
10
|
+
gem.files = `git ls-files`.split($\)
|
11
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
12
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
|
+
gem.name = 'sequel-protobuf'
|
14
|
+
gem.require_paths = ['lib']
|
15
|
+
gem.version = Sequel::Plugins::Protobuf::VERSION
|
16
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
|
4
|
+
require 'protocol_buffers'
|
5
|
+
|
6
|
+
module Test
|
7
|
+
# forward declarations
|
8
|
+
class MyMessage < ::ProtocolBuffers::Message; end
|
9
|
+
class MyMessageWithNested < ::ProtocolBuffers::Message; end
|
10
|
+
class Nested < ::ProtocolBuffers::Message; end
|
11
|
+
|
12
|
+
class MyMessage < ::ProtocolBuffers::Message
|
13
|
+
set_fully_qualified_name "Test.MyMessage"
|
14
|
+
|
15
|
+
required :int64, :id, 1
|
16
|
+
optional :string, :myField, 2
|
17
|
+
end
|
18
|
+
|
19
|
+
class MyMessageWithNested < ::ProtocolBuffers::Message
|
20
|
+
set_fully_qualified_name "Test.MyMessageWithNested"
|
21
|
+
|
22
|
+
required :int64, :id, 1
|
23
|
+
optional :string, :myField, 2
|
24
|
+
repeated ::Test::Nested, :nested, 3
|
25
|
+
end
|
26
|
+
|
27
|
+
class Nested < ::ProtocolBuffers::Message
|
28
|
+
set_fully_qualified_name "Test.Nested"
|
29
|
+
|
30
|
+
required :int64, :id, 1
|
31
|
+
optional :string, :nestedField, 2
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
package Test;
|
2
|
+
|
3
|
+
message MyMessage {
|
4
|
+
required int64 id = 1;
|
5
|
+
optional string myField = 2;
|
6
|
+
}
|
7
|
+
|
8
|
+
message MyMessageWithNested {
|
9
|
+
required int64 id = 1;
|
10
|
+
optional string myField = 2;
|
11
|
+
repeated Nested nested = 3;
|
12
|
+
}
|
13
|
+
|
14
|
+
message Nested {
|
15
|
+
required int64 id = 1;
|
16
|
+
optional string nestedField = 2;
|
17
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'sequel/plugins/protobuf/drivers/ruby-protocol-buffers-driver'
|
2
|
+
|
3
|
+
class RubyProtocolBuffersDriverTest < Minitest::Test
|
4
|
+
# Ensures that a protocol buffer defition can be serailized as expected
|
5
|
+
# with ruby-protocol-buffers as the driver
|
6
|
+
def test_serialize
|
7
|
+
d = Sequel::Plugins::Protobuf::DRIVERS[:ruby_protocol_buffers]
|
8
|
+
res = d.serialize(::Test::MyMessage, {:id => 1, :myField => "test"})
|
9
|
+
assert_equal("\b\x01\x12\x04test", res)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Ensures that the return type of the create method is that of the passed in protobuf model
|
13
|
+
def test_create
|
14
|
+
d = Sequel::Plugins::Protobuf::DRIVERS[:ruby_protocol_buffers]
|
15
|
+
res = d.create(::Test::MyMessage, {:id => 1, :myField => "test"})
|
16
|
+
assert_equal(res.class, ::Test::MyMessage)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Ensures that result of serialize can read with the driver's call to `parse`
|
20
|
+
# Also ensures that a successful parse will result in a new protobuf model
|
21
|
+
# with the expected fields
|
22
|
+
def test_parse
|
23
|
+
d = Sequel::Plugins::Protobuf::DRIVERS[:ruby_protocol_buffers]
|
24
|
+
msg = ::Test::MyMessage.new({:id => 1, :myField => "test"})
|
25
|
+
res = d.serialize(::Test::MyMessage, {:id => 1, :myField => "test"})
|
26
|
+
res2 = d.parse(::Test::MyMessage, res)
|
27
|
+
assert_equal(msg, res2)
|
28
|
+
assert_equal(res2.myField, "test")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Ensures that passing an attributes hash that is mismatched with the
|
32
|
+
# Protobuf definition will be coerced into an acceptable attributes hash
|
33
|
+
# such that it can be serialized as defined
|
34
|
+
def test_serialize_with_mismatched_attributes
|
35
|
+
e = nil
|
36
|
+
begin
|
37
|
+
d = Sequel::Plugins::Protobuf::DRIVERS[:ruby_protocol_buffers]
|
38
|
+
res = d.serialize(::Test::MyMessage, {:id => 1, :myField => "test", :garbage => "garbage_data"})
|
39
|
+
assert_equal("\b\x01\x12\x04test", res)
|
40
|
+
rescue ::Exception => e
|
41
|
+
# No-op
|
42
|
+
end
|
43
|
+
|
44
|
+
assert e.nil?, "We should not encounter an error when attempting to serialize a model with mismatched attributes"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Ensures that we do encounter an error when an insufficent attributes hash
|
48
|
+
# Is passed to a call to serialization
|
49
|
+
def test_serialize_with_mismatched_attributes_error
|
50
|
+
e = nil
|
51
|
+
begin
|
52
|
+
d = Sequel::Plugins::Protobuf::DRIVERS[:ruby_protocol_buffers]
|
53
|
+
res = d.serialize(::Test::MyMessage, {})
|
54
|
+
rescue ::Exception => e
|
55
|
+
# No-op
|
56
|
+
end
|
57
|
+
|
58
|
+
assert !e.nil?, "We should encounter an error when attempting to serialize a model with insufficient attributes"
|
59
|
+
assert_equal e.class, ::ProtocolBuffers::EncodeError
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
$LOAD_PATH.unshift(".")
|
2
|
+
|
3
|
+
require 'sequel/plugins/protobuf'
|
4
|
+
|
5
|
+
class ProtobufTest < Minitest::Test
|
6
|
+
def test_mixin
|
7
|
+
require 'test/helpers/my_message_sequel_model'
|
8
|
+
|
9
|
+
m = MyMessageSequelModel.create
|
10
|
+
assert m.respond_to?(:to_protobuf), "A new sequel model should respond to `to_protobuf`"
|
11
|
+
assert m.class.respond_to?(:from_protobuf), "The class of a new sequel model should respond to `from_protobuf`"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_mixin_error
|
15
|
+
begin
|
16
|
+
require 'test/helpers/definition_error_sequel_model'
|
17
|
+
rescue Exception => e
|
18
|
+
assert_equal e.class, Sequel::Plugins::Protobuf::MissingProtobufDefinitionError
|
19
|
+
assert_equal e.to_s, "Protobuf model definition was not specified."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_to_protobuf
|
24
|
+
require 'test/helpers/my_message_sequel_model'
|
25
|
+
|
26
|
+
m = MyMessageSequelModel.create({:myField => "test"})
|
27
|
+
res = m.to_protobuf
|
28
|
+
|
29
|
+
assert_equal res, "\b\x01\x12\x04test"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_from_protobuf
|
33
|
+
require 'test/helpers/my_message_sequel_model'
|
34
|
+
|
35
|
+
m = MyMessageSequelModel.from_protobuf("\b\x01\x12\x04test")
|
36
|
+
|
37
|
+
assert_equal m.id, 1
|
38
|
+
assert_equal m.myField, "test"
|
39
|
+
assert_equal m.class, MyMessageSequelModel
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_as_protobuf
|
43
|
+
require 'test/helpers/my_message_sequel_model'
|
44
|
+
|
45
|
+
attributes = {:myField => "test", :extraField => "extra"}
|
46
|
+
m = MyMessageSequelModel.create(attributes)
|
47
|
+
proto = m.as_protobuf
|
48
|
+
|
49
|
+
attributes.delete(:extraField)
|
50
|
+
expected = attributes.merge({:id => m.id})
|
51
|
+
|
52
|
+
res = proto.fields.inject([]) do |acc, (k, v)|
|
53
|
+
acc << v.name
|
54
|
+
acc
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_equal 1, proto.id
|
58
|
+
assert_equal "test", proto.myField
|
59
|
+
assert !proto.respond_to?(:extraField), "Expects protobuf model to not respond to a field that is not defined"
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_dataset_to_protobuf
|
63
|
+
require 'test/helpers/my_message_sequel_model'
|
64
|
+
|
65
|
+
m = MyMessageSequelModel.create({:myField => "test"})
|
66
|
+
collection = MyMessageSequelModel.where(:myField => "test")
|
67
|
+
|
68
|
+
res = collection.to_protobuf
|
69
|
+
|
70
|
+
assert_equal(res.length, 1)
|
71
|
+
assert_equal(res[0], "\b\x01\x12\x04test")
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_to_protobuf_nested_model
|
75
|
+
require 'test/helpers/my_message_sequel_model'
|
76
|
+
require 'test/helpers/nested_sequel_model'
|
77
|
+
|
78
|
+
m = MyMessageSequelModel.create({:myField => "test"})
|
79
|
+
m2 = NestedSequelModel.create({:my_message_id => m.id, :nestedField => "test-nested"})
|
80
|
+
|
81
|
+
m.reload
|
82
|
+
res = m.to_protobuf({
|
83
|
+
:as => ::Test::MyMessageWithNested,
|
84
|
+
:include => {
|
85
|
+
:nested => {
|
86
|
+
:as => ::Test::Nested
|
87
|
+
}
|
88
|
+
}
|
89
|
+
})
|
90
|
+
|
91
|
+
assert_equal(res, "\b\x01\x12\x04test\x1A\x0F\b\x01\x12\vtest-nested")
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_to_protobuf_with_coerced_keys
|
96
|
+
require 'test/helpers/my_message_sequel_model'
|
97
|
+
require 'test/helpers/nested_sequel_model'
|
98
|
+
|
99
|
+
m = MyMessageSequelModel.create({:myField => "test"})
|
100
|
+
m.reload
|
101
|
+
|
102
|
+
res = m.to_protobuf({
|
103
|
+
:coerce => {
|
104
|
+
:myField => Proc.new { |value|
|
105
|
+
"#{value}-coerced"
|
106
|
+
}
|
107
|
+
}
|
108
|
+
})
|
109
|
+
|
110
|
+
assert_equal("\b\x01\x12\ftest-coerced", res)
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
# Ensures that coercing the values of a sequel model
|
115
|
+
# does not mutate the values hash of that particular instance.
|
116
|
+
def test_values_retention_after_rendering_with_coercion
|
117
|
+
require 'test/helpers/my_message_sequel_model'
|
118
|
+
require 'test/helpers/nested_sequel_model'
|
119
|
+
|
120
|
+
m = MyMessageSequelModel.create({:myField => "test"})
|
121
|
+
m.reload
|
122
|
+
|
123
|
+
res = m.to_protobuf({
|
124
|
+
:coerce => {
|
125
|
+
:myField => Proc.new { |value|
|
126
|
+
"#{value}-coerced"
|
127
|
+
}
|
128
|
+
}
|
129
|
+
})
|
130
|
+
|
131
|
+
assert_equal("\b\x01\x12\ftest-coerced", res)
|
132
|
+
assert_equal("test", m.values[:myField])
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__))
|
2
|
+
|
3
|
+
# Simplecov needs to be required before test/unit
|
4
|
+
# in order for the test suite runner to be tracked during code-coverage generation
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start
|
7
|
+
|
8
|
+
require 'minitest'
|
9
|
+
require 'minitest/autorun'
|
10
|
+
require 'mocha/setup'
|
11
|
+
require 'sequel'
|
12
|
+
|
13
|
+
Sequel.mock(:fetch => [{ :id => 1,
|
14
|
+
:myField => "test",
|
15
|
+
:extraField => "extra",
|
16
|
+
:nestedField => "test-nested"}],
|
17
|
+
|
18
|
+
:columns => [:id,
|
19
|
+
:myField,
|
20
|
+
:extraField,
|
21
|
+
:my_message_id,
|
22
|
+
:nestedField])
|
23
|
+
|
24
|
+
# Require all protobuf definitions
|
25
|
+
Dir["**/*.pb.rb"].each do |f|
|
26
|
+
require File.absolute_path(f)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Require unit tests
|
30
|
+
Dir["**/*_test.rb"].each do |f|
|
31
|
+
require File.absolute_path(f)
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel-protobuf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kellydunn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Sequel plugin for protocol buffer serialization
|
14
|
+
email:
|
15
|
+
- defaultstring+sequel-protobuf@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- .gitignore
|
21
|
+
- Gemfile
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/sequel/plugins/protobuf.rb
|
25
|
+
- lib/sequel/plugins/protobuf/drivers.rb
|
26
|
+
- lib/sequel/plugins/protobuf/drivers/ruby-protocol-buffers-driver.rb
|
27
|
+
- lib/sequel/plugins/protobuf/version.rb
|
28
|
+
- sequel-protobuf.gemspec
|
29
|
+
- test/helpers/definition_error_sequel_model.rb
|
30
|
+
- test/helpers/models/test.pb.rb
|
31
|
+
- test/helpers/models/test.proto
|
32
|
+
- test/helpers/my_message_sequel_model.rb
|
33
|
+
- test/helpers/nested_sequel_model.rb
|
34
|
+
- test/sequel/plugins/protobuf/drivers/ruby_protocol_buffers_test.rb
|
35
|
+
- test/sequel/plugins/protobuf_test.rb
|
36
|
+
- test/test_helper.rb
|
37
|
+
homepage: http://github.com/kellydunn/sequel-protobuf
|
38
|
+
licenses: []
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.4.7
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Sequel plugin for protocol buffer serialization
|
60
|
+
test_files:
|
61
|
+
- test/helpers/definition_error_sequel_model.rb
|
62
|
+
- test/helpers/models/test.pb.rb
|
63
|
+
- test/helpers/models/test.proto
|
64
|
+
- test/helpers/my_message_sequel_model.rb
|
65
|
+
- test/helpers/nested_sequel_model.rb
|
66
|
+
- test/sequel/plugins/protobuf/drivers/ruby_protocol_buffers_test.rb
|
67
|
+
- test/sequel/plugins/protobuf_test.rb
|
68
|
+
- test/test_helper.rb
|
69
|
+
has_rdoc:
|