protobuf-activerecord 1.1.1 → 1.2.0.rc1

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.
@@ -20,6 +20,11 @@ module Protoable
20
20
  # given not callable.
21
21
  class FieldConverterError < ProtoableError
22
22
  end
23
+
24
+ # Raised by Protoable.field_from_record when the convert method
25
+ # given not callable.
26
+ class FieldTransformerError < ProtoableError
27
+ end
23
28
 
24
29
  # Raised by Protoable.field_scope when given scope is not defined.
25
30
  class SearchScopeError < ProtoableError
@@ -84,12 +84,12 @@ module Protoable
84
84
  #
85
85
  # Examples:
86
86
  # attribute_from_proto :public_key, :extract_public_key_from_proto
87
- # attribute_from_proto :status, lambda { |proto_field| # Do some stuff... }
88
- # attribute_from_proto :status do |proto_field|
87
+ # attribute_from_proto :status, lambda { |proto| # Do some stuff... }
88
+ # attribute_from_proto :status do |proto|
89
89
  # # Do some blocky stuff...
90
90
  # end
91
91
  #
92
- def attribute_from_proto(field, transformer = nil, &blk)
92
+ def attribute_from_proto(attribute, transformer = nil, &blk)
93
93
  transformer ||= blk
94
94
 
95
95
  if transformer.is_a?(Symbol)
@@ -102,12 +102,7 @@ module Protoable
102
102
  raise AttributeTransformerError, 'Attribute transformers need a callable or block!'
103
103
  end
104
104
 
105
- _protobuf_attribute_transformers[field.to_sym] = callable
106
- end
107
-
108
- def transform_column(field, transformer = nil, &blk)
109
- warn "[DEPRECATION] `transform_column` is deprecated and will be removed in v1.2. Please use `attribute_from_proto` instead."
110
- attribute_from_proto(field, transformer, &blk)
105
+ _protobuf_attribute_transformers[attribute.to_sym] = callable
111
106
  end
112
107
  end
113
108
  end
@@ -2,6 +2,18 @@ module Protoable
2
2
  module Persistence
3
3
  def self.included(klass)
4
4
  klass.extend Protoable::Persistence::ClassMethods
5
+
6
+ klass.class_eval do
7
+ # Override Active Record's initialize method so it can accept a protobuf
8
+ # message as it's attributes. Need to do it in class_eval block since initialize
9
+ # is defined in ActiveRecord::Base.
10
+ # :noapi:
11
+ def initialize(*args)
12
+ args[0] = attributes_from_proto(args.first) if args.first.is_a?(::Protobuf::Message)
13
+
14
+ super(*args)
15
+ end
16
+ end
5
17
  end
6
18
 
7
19
  module ClassMethods
@@ -8,20 +8,51 @@ module Protoable
8
8
 
9
9
  klass.class_eval do
10
10
  class << self
11
- attr_accessor :_protobuf_attribute_converters, :protobuf_fields
11
+ attr_accessor :_protobuf_attribute_converters,
12
+ :_protobuf_field_transformers, :protobuf_fields
12
13
  end
13
14
 
14
15
  @_protobuf_attribute_converters = {}
16
+ @_protobuf_field_transformers = {}
15
17
  @protobuf_fields = []
16
18
 
17
- inheritable_attributes :_protobuf_attribute_converters, :protobuf_fields, :protobuf_message
19
+ inheritable_attributes :_protobuf_attribute_converters,
20
+ :_protobuf_field_transformers, :protobuf_fields, :protobuf_message
18
21
  end
19
22
  end
20
23
 
21
24
  module ClassMethods
22
- def convert_column(field, converter = nil, &blk)
23
- warn "[DEPRECATION] `convert_column` is deprecated and will be removed in v1.2. Please use `protoable_attribute` instead."
24
- protoable_attribute(field, converter, &blk)
25
+ # Define a field transformation from a record. Accepts a Symbol,
26
+ # callable, or block that is called with the record being serialized.
27
+ #
28
+ # When given a callable or block, it is directly used to convert the field.
29
+ #
30
+ # When a symbol is given, it extracts the method with the same name.
31
+ #
32
+ # The callable or method must accept a single parameter, which is the
33
+ # proto message.
34
+ #
35
+ # Examples:
36
+ # field_from_record :public_key, :convert_public_key_to_proto
37
+ # field_from_record :status, lambda { |record| # Do some stuff... }
38
+ # field_from_record :status do |record|
39
+ # # Do some blocky stuff...
40
+ # end
41
+ #
42
+ def field_from_record(field, transformer = nil, &blk)
43
+ transformer ||= blk
44
+
45
+ if transformer.is_a?(Symbol)
46
+ callable = lambda { |value| self.__send__(transformer, value) }
47
+ else
48
+ callable = transformer
49
+ end
50
+
51
+ unless callable.respond_to?(:call)
52
+ raise FieldTransformerError, 'Attribute transformers need a callable or block!'
53
+ end
54
+
55
+ _protobuf_field_transformers[field.to_sym] = callable
25
56
  end
26
57
 
27
58
  # Define a custom attribute conversion for serialization to protobuf.
@@ -98,8 +129,12 @@ module Protoable
98
129
  #
99
130
  def protoable_attributes
100
131
  protoable_attributes = protobuf_fields.inject({}) do |hash, field|
101
- value = respond_to?(field) ? __send__(field) : nil
102
- hash[field] = _protobuf_convert_attributes_to_fields(field, value)
132
+ if _protobuf_field_transformers.has_key?(field)
133
+ hash[field] = _protobuf_field_transformers[field].call(self)
134
+ else
135
+ value = respond_to?(field) ? __send__(field) : nil
136
+ hash[field] = _protobuf_convert_attributes_to_fields(field, value)
137
+ end
103
138
  hash
104
139
  end
105
140
 
@@ -112,6 +147,10 @@ module Protoable
112
147
  self.class._protobuf_convert_attributes_to_fields(field, value)
113
148
  end
114
149
 
150
+ def _protobuf_field_transformers
151
+ self.class._protobuf_field_transformers
152
+ end
153
+
115
154
  def protobuf_fields
116
155
  self.class.protobuf_fields
117
156
  end
@@ -1,5 +1,5 @@
1
1
  module Protobuf
2
2
  module ActiveRecord
3
- VERSION = "1.1.1"
3
+ VERSION = "1.2.0.rc1"
4
4
  end
5
5
  end
@@ -31,14 +31,14 @@ describe Protoable::Persistence do
31
31
  end
32
32
 
33
33
  describe ".attributes_from_proto" do
34
- context "when a attribute transformer is defined for the field" do
34
+ context "when a transformer is defined for the attribute" do
35
35
  it "transforms the field value" do
36
36
  attribute_fields = User.attributes_from_proto(proto)
37
37
  attribute_fields[:first_name].should eq user_attributes[:first_name]
38
38
  end
39
39
  end
40
40
 
41
- context "when attribute transformer is not defined for the field" do
41
+ context "when a transformer is not defined for the attribute" do
42
42
  before {
43
43
  User.stub(:_protobuf_convert_fields_to_columns) do |key, value|
44
44
  value
@@ -3,6 +3,38 @@ require 'spec_helper'
3
3
  describe Protoable::Serialization do
4
4
  let(:protobuf_message) { UserMessage }
5
5
 
6
+ describe ".field_from_record" do
7
+ context "when the given converter is a symbol" do
8
+ let(:callable) { lambda { |value| User.__send__(:extract_first_name) } }
9
+
10
+ before { User.field_from_record :first_name, :extract_first_name }
11
+
12
+ it "creates a callable method object from the converter" do
13
+ User.should_receive(:extract_first_name)
14
+ User._protobuf_field_transformers[:first_name].call(1)
15
+ end
16
+ end
17
+
18
+ context "when the given converter is not callable" do
19
+ it "raises an exception" do
20
+ expect { User.field_from_record :name, nil }.to raise_exception(Protoable::FieldTransformerError)
21
+ end
22
+ end
23
+
24
+ context "when the given transformer is callable" do
25
+ let(:callable) { lambda { |proto| nil } }
26
+
27
+ before {
28
+ User.stub(:_protobuf_field_transformers).and_return(Hash.new)
29
+ User.field_from_record :account_id, callable
30
+ }
31
+
32
+ it "adds the given converter to the list of protobuf field transformers" do
33
+ User._protobuf_field_transformers[:account_id] = callable
34
+ end
35
+ end
36
+ end
37
+
6
38
  describe ".protoable_attribute" do
7
39
  context "when the given converter is a hash" do
8
40
  let(:method) { lambda { |value| User.__send__(:convert_base64_to_string, value) } }
@@ -47,7 +79,7 @@ describe Protoable::Serialization do
47
79
  before { User.protobuf_message(protobuf_message) }
48
80
 
49
81
  context "given a value" do
50
- let(:protobuf_fields) { [ :guid, :name, :email ] }
82
+ let(:protobuf_fields) { [ :guid, :name, :email, :email_domain ] }
51
83
 
52
84
  it "sets .protobuf_fields" do
53
85
  User.protobuf_fields.should =~ protobuf_fields
@@ -74,23 +106,46 @@ describe Protoable::Serialization do
74
106
  before { User.protobuf_message(protobuf_message) }
75
107
 
76
108
  describe "#protoable_attributes" do
77
- let(:attributes) {
78
- {
79
- :guid => "foo",
80
- :first_name => "bar",
81
- :last_name => "baz",
82
- :email => "foo@test.co"
109
+ context "when a transformer is defined for the field" do
110
+ let(:attributes) {
111
+ {
112
+ :guid => "foo",
113
+ :first_name => "bar",
114
+ :last_name => "baz",
115
+ :email => "foo@test.co"
116
+ }
117
+ }
118
+ let(:protoable_attributes) { { :guid => user.guid, :name => user.name, :email => user.email, :email_domain => 'test.co' } }
119
+ let(:transformer) { { :email_domain => lambda { |record| record.email.split('@').last } } }
120
+
121
+ before {
122
+ User.stub(:_protobuf_field_transformers).and_return(transformer)
83
123
  }
84
- }
85
- let(:protoable_attributes) { { :guid => user.guid, :name => user.name, :email => user.email } }
86
124
 
87
- it "returns a hash of protobuf fields that this object has getters for" do
88
- user.protoable_attributes.should eq protoable_attributes
125
+ it "gets the field from the transformer" do
126
+ user.protoable_attributes.should eq protoable_attributes
127
+ end
89
128
  end
90
129
 
91
- it "converts attributes values for protobuf messages" do
92
- user.should_receive(:_protobuf_convert_attributes_to_fields).any_number_of_times
93
- user.protoable_attributes
130
+ context "when a transformer is not defined for the field" do
131
+ let(:attributes) {
132
+ {
133
+ :guid => "foo",
134
+ :first_name => "bar",
135
+ :last_name => "baz",
136
+ :email => "foo@test.co"
137
+ }
138
+ }
139
+ let(:protoable_attributes) { { :guid => user.guid, :name => user.name, :email => user.email, :email_domain => nil } }
140
+
141
+ it "returns a hash of protobuf fields that this object has getters for" do
142
+ user.protoable_attributes.should eq protoable_attributes
143
+ end
144
+
145
+ it "converts attributes values for protobuf messages" do
146
+ user.should_receive(:_protobuf_convert_attributes_to_fields).any_number_of_times
147
+ user.protoable_attributes
148
+ end
94
149
  end
95
150
  end
96
151
 
@@ -1,7 +1,8 @@
1
1
  message UserMessage {
2
- optional string guid = 1;
3
- optional string name = 2;
4
- optional string email = 3;
2
+ optional string guid = 1;
3
+ optional string name = 2;
4
+ optional string email = 3;
5
+ optional string email_domain = 4;
5
6
  }
6
7
 
7
8
  message UserSearchMessage {
@@ -1,2 +1 @@
1
- require 'protobuf'
2
1
  require 'support/protobuf/user.pb'
@@ -17,6 +17,7 @@ class UserMessage
17
17
  optional ::Protobuf::Field::StringField, :guid, 1
18
18
  optional ::Protobuf::Field::StringField, :name, 2
19
19
  optional ::Protobuf::Field::StringField, :email, 3
20
+ optional ::Protobuf::Field::StringField, :email_domain, 4
20
21
  end
21
22
 
22
23
  class UserSearchMessage
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
5
- prerelease:
4
+ version: 1.2.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Adam Hutchison
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-12 00:00:00.000000000 Z
12
+ date: 2012-11-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -240,16 +240,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
240
240
  version: '0'
241
241
  segments:
242
242
  - 0
243
- hash: 471675617945359118
243
+ hash: -3851235925633840978
244
244
  required_rubygems_version: !ruby/object:Gem::Requirement
245
245
  none: false
246
246
  requirements:
247
- - - ! '>='
247
+ - - ! '>'
248
248
  - !ruby/object:Gem::Version
249
- version: '0'
250
- segments:
251
- - 0
252
- hash: 471675617945359118
249
+ version: 1.3.1
253
250
  requirements: []
254
251
  rubyforge_project:
255
252
  rubygems_version: 1.8.24