protobuf-activerecord 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -4,6 +4,10 @@ source 'https://rubygems.org'
4
4
  # Specify your gem's dependencies in protobuf-activerecord.gemspec
5
5
  gemspec
6
6
 
7
- gem 'builder', '~> 3.0.3'
7
+ gem 'builder', '~> 3.0.4' # Builder 3.1.x is not supported by Active Record
8
+ # and Bundler has trouble resolving the dependency
9
+ # with Geminabox.
8
10
 
9
- gem 'timecop', '~> 0.3.5', :group => :development
11
+ gem 'timecop', '~> 0.3.5', :group => :development # Timecop 0.4.x is has a bug
12
+ # when dealing with timezones
13
+ # on Time objects.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Protobuf ActiveRecord
2
2
 
3
- Protobuf Active Record provides the ability to create Active Record objects from Protocol Buffer messages and vice versa. It adds methods that allow you to create, update, and destroy Active Record objects from protobuf messages. It also provides methods to serialize Active Record objects to protobuf messages.
3
+ Protobuf Active Record provides the ability to create and update Active Record objects from protobuf messages and to serialize Active Record objects to protobuf messages.
4
4
 
5
5
  ## Installation
6
6
 
@@ -21,14 +21,12 @@ Or install it yourself as:
21
21
  Protobuf Active Record's functionality is contained within the `Protoable` module. To endow your Active Record models with the protoable behaviour, simply include it into your model:
22
22
 
23
23
  ```Ruby
24
+ class User < ActiveRecord::Base
25
+ include Protoable
24
26
 
25
- class User < ActiveRecord::Base
26
- include Protoable
27
-
28
- # Your awesome methods...
29
- #
30
- end
31
-
27
+ # Your awesome methods...
28
+ #
29
+ end
32
30
  ```
33
31
 
34
32
  Now you can pass protobuf messages to your user model just like you would attributes. Protoable will take care of converting the protobuf message to attributes and continue on with Active Record's normal behavior.
@@ -40,29 +38,25 @@ Just like Active Record maps database columns to your model's attributes, Protoa
40
38
  Given a table that looks like this:
41
39
 
42
40
  ```Ruby
43
-
44
- create_table :users do |t|
45
- t.string :first_name
46
- t.string :last_name
47
- t.string :email
48
- t.integer :account_id
49
-
50
- t.timestamps
51
- end
52
-
41
+ create_table :users do |t|
42
+ t.string :first_name
43
+ t.string :last_name
44
+ t.string :email
45
+ t.integer :account_id
46
+
47
+ t.timestamps
48
+ end
53
49
  ```
54
50
 
55
51
  and a protobuf message that looks like this:
56
52
 
57
53
  ```Ruby
58
-
59
- class UserMessage < ::Protobuf::Message
60
- optional ::Protobuf::Field::StringField, :first_name, 1
61
- optional ::Protobuf::Field::StringField, :last_name, 2
62
- optional ::Protobuf::Field::StringField, :email, 3
63
- optional ::Protobuf::Field::IntegerField, :account_id, 4
64
- end
65
-
54
+ class UserMessage < ::Protobuf::Message
55
+ optional ::Protobuf::Field::StringField, :first_name, 1
56
+ optional ::Protobuf::Field::StringField, :last_name, 2
57
+ optional ::Protobuf::Field::StringField, :email, 3
58
+ optional ::Protobuf::Field::IntegerField, :account_id, 4
59
+ end
66
60
  ```
67
61
 
68
62
  Protoable will map the `first_name`, `last_name`, `email`, & `account_id` columns, skipping the timestamp columns. Repeated fields and fields that are nil will not be mapped.
@@ -74,42 +68,87 @@ Since Protocol Buffer messages don't support sending date, time, or datetime fie
74
68
  Picking up our users table example again, if you wanted to add a `created_at` field to your protobuf message, if you add it as an integer field, Protoable will handle the conversions for you:
75
69
 
76
70
  ```Ruby
77
-
78
- class UserMessage < ::Protobuf::Message
79
- optional ::Protobuf::Field::StringField, :first_name, 1
80
- optional ::Protobuf::Field::StringField, :last_name, 2
81
- optional ::Protobuf::Field::StringField, :email, 3
82
- optional ::Protobuf::Field::IntegerField, :account_id, 4
83
-
84
- # Add a datetime field as an integer and Protoable will map it for you
85
- optional ::Protobuf::Field::IntegerField, :created_at, 5
86
- end
87
-
71
+ class UserMessage < ::Protobuf::Message
72
+ optional ::Protobuf::Field::StringField, :first_name, 1
73
+ optional ::Protobuf::Field::StringField, :last_name, 2
74
+ optional ::Protobuf::Field::StringField, :email, 3
75
+ optional ::Protobuf::Field::IntegerField, :account_id, 4
76
+
77
+ # Add a datetime field as an integer and Protoable will map it for you
78
+ optional ::Protobuf::Field::IntegerField, :created_at, 5
79
+ end
88
80
  ```
89
81
 
90
82
  **Mass-assignment**
91
83
 
92
84
  If a model has protected attributes defined, Protoable will skip any fields that map to them. Likewise, if there are accessible attributes defined, only they will be mapped.
93
85
 
94
- ### Persistence
86
+ ### Creating/Updating
95
87
 
96
88
  Protoable doesn't alter Active Record's normal persistence methods. It simply adds to ability to pass protobuf messages to them in place of an attributes hash.
97
89
 
98
- ### Serialization
90
+ ### Serialization to protobuf
99
91
 
100
92
  In addition to mapping protobuf message fields to Active Record objects when creating or updating records, Protoable also provides the ability to serialize Active Record objects to protobuf messages. Simply tell Protoable the protobuf message that should be used and it will take care of the rest:
101
93
 
102
94
  ```Ruby
95
+ class User < ActiveRecord::Base
96
+ include Protoable
103
97
 
104
- class User < ActiveRecord::Base
105
- # Configures Protoable to use the UserMessage class and adds a :to_proto method.
106
- protobuf_message :user_message
107
- end
108
-
98
+ # Configures Protoable to use the UserMessage class and adds :to_proto.
99
+ protobuf_message :user_message
100
+ end
109
101
  ```
110
102
 
111
103
  Once the desired protobuf message has been specified, Protoable adds a `to_proto` method to the model. Calling `to_proto` will automatically convert the model to the specified protobuf message using the same attribute to field mapping it uses to create and update objects from protobuf messages.
112
104
 
105
+ ### Field & column converters
106
+
107
+ Protoable will handle regular field conversions out of the box, but for those times when custom conversions are needed, they can be defined with the `convert_field` and `convert_column` methods. Field converters are used when creating or updating objects from a protobuf message and column converters are used when serializing objects to protobuf messages.
108
+
109
+ `convert_field` and `convert_column` both take the name of the field/column being converted and a method name or callable (lambda or proc). when converting that field, calls the given callable, passing it the value of the field being converted.
110
+
111
+ **Converting fields**
112
+
113
+ ```Ruby
114
+ class User < ActiveRecord::Base
115
+ include Protoable
116
+
117
+ # Calls :map_status_from_proto when creating/updating objects, passing it the
118
+ # value of the status field from the protobuf message.
119
+ def self.map_status_from_proto(field_value)
120
+ # Some custom mapping
121
+ end
122
+ convert_field :status, :map_status_from_proto
123
+ end
124
+ ```
125
+
126
+ **Converting columns**
127
+
128
+ ```Ruby
129
+ class User < ActiveRecord::Base
130
+ include Protoable
131
+
132
+ # Calls the lambda when serializing objects to protobuf messages, passing it
133
+ # the value of the status column from the database.
134
+ convert_column :status, lambda { |column_value| column_value_.to_s }
135
+ end
136
+ ```
137
+
138
+ ### Column transformers
139
+
140
+ Protoable handles mapping protobuf message fields to object attributes, but what happens when an attribute doesn't have a matching field? Using the `transform_column` method, you can define custom column transformations. Simply call `transform_column`, passing it the name of the column and a method name or callable (lambda or proc). When creating or updating objects, Protoable will call the transformer, passing it the protobuf message.
141
+
142
+ ```Ruby
143
+ class User < ActiveRecord::Base
144
+ include Protoable
145
+
146
+ # Calls the lambda when creating/updating objects, passing it the protobuf
147
+ # message.
148
+ transform_column :account_id, lambda { |protobuf_message| # Some custom transformation... }
149
+ end
150
+ ```
151
+
113
152
  ## Contributing
114
153
 
115
154
  1. Fork it
@@ -53,14 +53,14 @@ module Protoable
53
53
 
54
54
  # :nodoc:
55
55
  def create(attributes, options = {}, &block)
56
- attributes = attributes_from_proto(proto) if attributes.is_a?(::Protobuf::Message)
56
+ attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
57
57
 
58
58
  super(attributes, options)
59
59
  end
60
60
 
61
61
  # :nodoc:
62
62
  def create!(attributes, options = {}, &block)
63
- attributes = attributes_from_proto(proto) if attributes.is_a?(::Protobuf::Message)
63
+ attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
64
64
 
65
65
  super(attributes, options)
66
66
  end
@@ -99,14 +99,14 @@ module Protoable
99
99
 
100
100
  # :nodoc:
101
101
  def update_attributes(attributes, options = {})
102
- attributes = attributes_from_proto(proto) if attributes.is_a?(::Protobuf::Message)
102
+ attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
103
103
 
104
104
  super(attributes, options)
105
105
  end
106
106
 
107
107
  # :nodoc:
108
108
  def update_attributes!(attributes, options = {})
109
- attributes = attributes_from_proto(proto) if attributes.is_a?(::Protobuf::Message)
109
+ attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
110
110
 
111
111
  super(attributes, options)
112
112
  end
@@ -1,5 +1,5 @@
1
1
  module Protobuf
2
2
  module ActiveRecord
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
5
5
  end
@@ -52,6 +52,30 @@ describe Protoable::Persistence do
52
52
  end
53
53
  end
54
54
 
55
+ describe ".create" do
56
+ it "accepts a protobuf message" do
57
+ User.any_instance.should_receive(:save)
58
+ User.create(proto)
59
+ end
60
+
61
+ it "accepts a hash" do
62
+ User.any_instance.should_receive(:save)
63
+ User.create(user_attributes)
64
+ end
65
+ end
66
+
67
+ describe ".create!" do
68
+ it "accepts a protobuf message" do
69
+ User.any_instance.should_receive(:save!)
70
+ User.create!(proto)
71
+ end
72
+
73
+ it "accepts a hash" do
74
+ User.any_instance.should_receive(:save!)
75
+ User.create!(user_attributes)
76
+ end
77
+ end
78
+
55
79
  describe ".create_from_proto" do
56
80
  it "initializes a new object with attributes from the given protobuf message" do
57
81
  user = User.create_from_proto(proto)
@@ -110,6 +134,30 @@ describe Protoable::Persistence do
110
134
  end
111
135
  end
112
136
 
137
+ describe ".update_attributes" do
138
+ it "accepts a protobuf message" do
139
+ User.any_instance.should_receive(:save)
140
+ user.update_attributes(proto)
141
+ end
142
+
143
+ it "accepts a hash" do
144
+ User.any_instance.should_receive(:save)
145
+ user.update_attributes(user_attributes)
146
+ end
147
+ end
148
+
149
+ describe ".update_attributes!" do
150
+ it "accepts a protobuf message" do
151
+ User.any_instance.should_receive(:save!)
152
+ user.update_attributes!(proto)
153
+ end
154
+
155
+ it "accepts a hash" do
156
+ User.any_instance.should_receive(:save!)
157
+ user.update_attributes!(user_attributes)
158
+ end
159
+ end
160
+
113
161
  describe "#update_from_proto" do
114
162
  it "updates the object with attributes from the given protobuf message" do
115
163
  user.should_receive(:assign_attributes).with(user_attributes, {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf-activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-28 00:00:00.000000000 Z
12
+ date: 2012-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -222,7 +222,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
222
  version: '0'
223
223
  segments:
224
224
  - 0
225
- hash: -2932429429413082945
225
+ hash: 763481842519497626
226
226
  required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  none: false
228
228
  requirements:
@@ -231,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
231
  version: '0'
232
232
  segments:
233
233
  - 0
234
- hash: -2932429429413082945
234
+ hash: 763481842519497626
235
235
  requirements: []
236
236
  rubyforge_project:
237
237
  rubygems_version: 1.8.24