protobuf-activerecord 1.2.6 → 2.0.0.beta
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.
- data/Gemfile +0 -4
 - data/lib/protobuf/activerecord/protoable.rb +4 -4
 - data/lib/protobuf/activerecord/protoable/columns.rb +56 -0
 - data/lib/protobuf/activerecord/protoable/errors.rb +0 -10
 - data/lib/protobuf/activerecord/protoable/persistence.rb +0 -91
 - data/lib/protobuf/activerecord/protoable/scope.rb +0 -2
 - data/lib/protobuf/activerecord/protoable/serialization.rb +87 -64
 - data/lib/protobuf/activerecord/protoable/transformation.rb +140 -0
 - data/lib/protobuf/activerecord/version.rb +1 -1
 - data/protobuf-activerecord.gemspec +1 -1
 - data/spec/protoable/columns_spec.rb +99 -0
 - data/spec/protoable/persistence_spec.rb +2 -180
 - data/spec/protoable/serialization_spec.rb +149 -76
 - data/spec/protoable/transformation_spec.rb +214 -0
 - data/spec/support/definitions/user.proto +1 -1
 - data/spec/support/models/user.rb +4 -8
 - data/spec/support/protobuf/user.pb.rb +1 -1
 - metadata +15 -18
 - data/lib/protobuf/activerecord/protoable/convert.rb +0 -79
 - data/lib/protobuf/activerecord/protoable/fields.rb +0 -109
 - data/spec/protoable/convert_spec.rb +0 -265
 - data/spec/protoable/fields_spec.rb +0 -102
 
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -6,7 +6,3 @@ gemspec 
     | 
|
| 
       6 
6 
     | 
    
         
             
            gem 'builder', '~> 3.0.4' # Builder 3.1.x is not supported by Active Record
         
     | 
| 
       7 
7 
     | 
    
         
             
                                      # and Bundler has trouble resolving the dependency
         
     | 
| 
       8 
8 
     | 
    
         
             
                                      # with Geminabox.
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            gem 'timecop', '~> 0.3.5', :group => :development # Timecop 0.4.x is has a bug
         
     | 
| 
       11 
     | 
    
         
            -
                                                              # when dealing with timezones
         
     | 
| 
       12 
     | 
    
         
            -
                                                              # on Time objects.
         
     | 
| 
         @@ -1,17 +1,17 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'protobuf/activerecord/protoable/ 
     | 
| 
      
 1 
     | 
    
         
            +
            require 'protobuf/activerecord/protoable/columns'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'protobuf/activerecord/protoable/errors'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'protobuf/activerecord/protoable/fields'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require 'protobuf/activerecord/protoable/persistence'
         
     | 
| 
       5 
4 
     | 
    
         
             
            require 'protobuf/activerecord/protoable/scope'
         
     | 
| 
       6 
5 
     | 
    
         
             
            require 'protobuf/activerecord/protoable/serialization'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'protobuf/activerecord/protoable/transformation'
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            module Protoable
         
     | 
| 
       9 
9 
     | 
    
         
             
              def self.included(klass)
         
     | 
| 
       10 
     | 
    
         
            -
                klass.extend Protoable::Fields
         
     | 
| 
       11 
10 
     | 
    
         
             
                klass.extend Protoable::Scope
         
     | 
| 
       12 
11 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                klass.__send__(:include, Protoable:: 
     | 
| 
      
 12 
     | 
    
         
            +
                klass.__send__(:include, Protoable::Columns)
         
     | 
| 
       14 
13 
     | 
    
         
             
                klass.__send__(:include, Protoable::Persistence)
         
     | 
| 
       15 
14 
     | 
    
         
             
                klass.__send__(:include, Protoable::Serialization)
         
     | 
| 
      
 15 
     | 
    
         
            +
                klass.__send__(:include, Protoable::Transformation)
         
     | 
| 
       16 
16 
     | 
    
         
             
              end
         
     | 
| 
       17 
17 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'heredity/inheritable_class_instance_variables'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Protoable
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Columns
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.included(klass)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  klass.extend Protoable::Columns::ClassMethods
         
     | 
| 
      
 7 
     | 
    
         
            +
                  klass.__send__(:include, ::Heredity::InheritableClassInstanceVariables)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  klass.class_eval do
         
     | 
| 
      
 10 
     | 
    
         
            +
                    class << self
         
     | 
| 
      
 11 
     | 
    
         
            +
                      attr_accessor :_protobuf_columns, :_protobuf_column_types
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    @_protobuf_columns = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @_protobuf_column_types = Hash.new { |h,k| h[k] = [] }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    # NOTE: Make sure each inherited object has the database layout
         
     | 
| 
      
 18 
     | 
    
         
            +
                    inheritable_attributes :_protobuf_columns, :_protobuf_column_types
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  _protobuf_map_columns(klass)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Map out the columns for future reference on type conversion
         
     | 
| 
      
 25 
     | 
    
         
            +
                #
         
     | 
| 
      
 26 
     | 
    
         
            +
                def self._protobuf_map_columns(klass)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  return unless klass.table_exists?
         
     | 
| 
      
 28 
     | 
    
         
            +
                  klass.columns.map do |column|
         
     | 
| 
      
 29 
     | 
    
         
            +
                    klass._protobuf_columns[column.name.to_sym] = column
         
     | 
| 
      
 30 
     | 
    
         
            +
                    klass._protobuf_column_types[column.type.to_sym] << column.name.to_sym
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # :nodoc:
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def _protobuf_date_column?(key)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    _protobuf_column_types.fetch(:date, false) && _protobuf_column_types[:date].include?(key)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  # :nodoc:
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def _protobuf_datetime_column?(key)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    _protobuf_column_types.fetch(:datetime, false) && _protobuf_column_types[:datetime].include?(key)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  # :nodoc:
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def _protobuf_time_column?(key)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    _protobuf_column_types.fetch(:time, false) && _protobuf_column_types[:time].include?(key)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # :nodoc:
         
     | 
| 
      
 51 
     | 
    
         
            +
                  def _protobuf_timestamp_column?(key)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    _protobuf_column_types.fetch(:timestamp, false) && _protobuf_column_types[:timestamp].include?(key)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -6,21 +6,11 @@ module Protoable 
     | 
|
| 
       6 
6 
     | 
    
         
             
              class ProtoableError < StandardError
         
     | 
| 
       7 
7 
     | 
    
         
             
              end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
              # Raised by Protoable.protoable_attribute when the convert method given is
         
     | 
| 
       10 
     | 
    
         
            -
              # not callable.
         
     | 
| 
       11 
     | 
    
         
            -
              class AttributeConverterError < ProtoableError
         
     | 
| 
       12 
     | 
    
         
            -
              end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
9 
     | 
    
         
             
              # Raised by Protoable.attribute_from_proto when the transformer method
         
     | 
| 
       15 
10 
     | 
    
         
             
              # given is not callable.
         
     | 
| 
       16 
11 
     | 
    
         
             
              class AttributeTransformerError < ProtoableError
         
     | 
| 
       17 
12 
     | 
    
         
             
              end
         
     | 
| 
       18 
13 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
              # Raised by Protoable.convert_field when the convert method
         
     | 
| 
       20 
     | 
    
         
            -
              # given not callable.
         
     | 
| 
       21 
     | 
    
         
            -
              class FieldConverterError < ProtoableError
         
     | 
| 
       22 
     | 
    
         
            -
              end
         
     | 
| 
       23 
     | 
    
         
            -
              
         
     | 
| 
       24 
14 
     | 
    
         
             
              # Raised by Protoable.field_from_record when the convert method
         
     | 
| 
       25 
15 
     | 
    
         
             
              # given not callable.
         
     | 
| 
       26 
16 
     | 
    
         
             
              class FieldTransformerError < ProtoableError
         
     | 
| 
         @@ -17,62 +17,6 @@ module Protoable 
     | 
|
| 
       17 
17 
     | 
    
         
             
                end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       20 
     | 
    
         
            -
                  # Filters accessible attributes that exist in the given protobuf message's
         
     | 
| 
       21 
     | 
    
         
            -
                  # fields or have attribute transformers defined for them.
         
     | 
| 
       22 
     | 
    
         
            -
                  #
         
     | 
| 
       23 
     | 
    
         
            -
                  # Returns a hash of attribute fields with their respective values.
         
     | 
| 
       24 
     | 
    
         
            -
                  #
         
     | 
| 
       25 
     | 
    
         
            -
                  def _filter_attribute_fields(proto)
         
     | 
| 
       26 
     | 
    
         
            -
                    fields = proto.to_hash
         
     | 
| 
       27 
     | 
    
         
            -
                    fields.select! { |key, value| proto.has_field?(key) && !proto.get_field_by_name(key).repeated? }
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    attribute_fields = _filtered_attributes.inject({}) do |hash, column_name|
         
     | 
| 
       30 
     | 
    
         
            -
                      symbolized_column = column_name.to_sym
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                      if fields.has_key?(symbolized_column) ||
         
     | 
| 
       33 
     | 
    
         
            -
                        _protobuf_attribute_transformers.has_key?(symbolized_column)
         
     | 
| 
       34 
     | 
    
         
            -
                        hash[symbolized_column] = fields[symbolized_column]
         
     | 
| 
       35 
     | 
    
         
            -
                      end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                      hash
         
     | 
| 
       38 
     | 
    
         
            -
                    end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                    attribute_fields
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  # Filters protected attributes from the available attributes list. When
         
     | 
| 
       44 
     | 
    
         
            -
                  # set through accessible attributes, returns the accessible attributes.
         
     | 
| 
       45 
     | 
    
         
            -
                  # When set through protected attributes, returns the attributes minus any
         
     | 
| 
       46 
     | 
    
         
            -
                  # protected attributes.
         
     | 
| 
       47 
     | 
    
         
            -
                  #
         
     | 
| 
       48 
     | 
    
         
            -
                  def _filtered_attributes
         
     | 
| 
       49 
     | 
    
         
            -
                    return accessible_attributes.to_a if accessible_attributes.present?
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                    return self.attribute_names - protected_attributes.to_a
         
     | 
| 
       52 
     | 
    
         
            -
                  end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                  # Creates a hash of attributes from a given protobuf message.
         
     | 
| 
       55 
     | 
    
         
            -
                  #
         
     | 
| 
       56 
     | 
    
         
            -
                  # It converts and transforms field values using the field converters and
         
     | 
| 
       57 
     | 
    
         
            -
                  # attribute transformers, ignoring repeated and nil fields.
         
     | 
| 
       58 
     | 
    
         
            -
                  #
         
     | 
| 
       59 
     | 
    
         
            -
                  def attributes_from_proto(proto)
         
     | 
| 
       60 
     | 
    
         
            -
                    attribute_fields = _filter_attribute_fields(proto)
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                    attributes = attribute_fields.inject({}) do |hash, (key, value)|
         
     | 
| 
       63 
     | 
    
         
            -
                      if _protobuf_attribute_transformers.has_key?(key)
         
     | 
| 
       64 
     | 
    
         
            -
                        attribute = _protobuf_attribute_transformers[key].call(proto)
         
     | 
| 
       65 
     | 
    
         
            -
                        hash[key] = attribute unless attribute.nil?
         
     | 
| 
       66 
     | 
    
         
            -
                      else
         
     | 
| 
       67 
     | 
    
         
            -
                        hash[key] = _protobuf_convert_fields_to_columns(key, value)
         
     | 
| 
       68 
     | 
    
         
            -
                      end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                      hash
         
     | 
| 
       71 
     | 
    
         
            -
                    end
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
                    attributes
         
     | 
| 
       74 
     | 
    
         
            -
                  end
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
20 
     | 
    
         
             
                  # :nodoc:
         
     | 
| 
       77 
21 
     | 
    
         
             
                  def create(attributes, options = {}, &block)
         
     | 
| 
       78 
22 
     | 
    
         
             
                    attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
         
     | 
| 
         @@ -86,17 +30,6 @@ module Protoable 
     | 
|
| 
       86 
30 
     | 
    
         | 
| 
       87 
31 
     | 
    
         
             
                    super(attributes, options)
         
     | 
| 
       88 
32 
     | 
    
         
             
                  end
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                  # Creates an object from the given protobuf message, if it's valid. The
         
     | 
| 
       91 
     | 
    
         
            -
                  # newly created object is returned if it was successfully saved or not.
         
     | 
| 
       92 
     | 
    
         
            -
                  #
         
     | 
| 
       93 
     | 
    
         
            -
                  def create_from_proto(proto, options = {})
         
     | 
| 
       94 
     | 
    
         
            -
                    attributes = attributes_from_proto(proto)
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                    yield(attributes) if block_given?
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                    self.create(attributes, options)
         
     | 
| 
       99 
     | 
    
         
            -
                  end
         
     | 
| 
       100 
33 
     | 
    
         
             
                end
         
     | 
| 
       101 
34 
     | 
    
         | 
| 
       102 
35 
     | 
    
         
             
                # :nodoc:
         
     | 
| 
         @@ -106,19 +39,6 @@ module Protoable 
     | 
|
| 
       106 
39 
     | 
    
         
             
                  super(attributes, options)
         
     | 
| 
       107 
40 
     | 
    
         
             
                end
         
     | 
| 
       108 
41 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                # Calls up to the class version of the method.
         
     | 
| 
       110 
     | 
    
         
            -
                #
         
     | 
| 
       111 
     | 
    
         
            -
                def attributes_from_proto(proto)
         
     | 
| 
       112 
     | 
    
         
            -
                  self.class.attributes_from_proto(proto)
         
     | 
| 
       113 
     | 
    
         
            -
                end
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                # Destroys the record. Mainly wrapped to provide a consistent API and
         
     | 
| 
       116 
     | 
    
         
            -
                # a convient way to override protobuf-specific destroy behavior.
         
     | 
| 
       117 
     | 
    
         
            -
                #
         
     | 
| 
       118 
     | 
    
         
            -
                def destroy_from_proto
         
     | 
| 
       119 
     | 
    
         
            -
                  destroy
         
     | 
| 
       120 
     | 
    
         
            -
                end
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
42 
     | 
    
         
             
                # :nodoc:
         
     | 
| 
       123 
43 
     | 
    
         
             
                def update_attributes(attributes, options = {})
         
     | 
| 
       124 
44 
     | 
    
         
             
                  attributes = attributes_from_proto(attributes) if attributes.is_a?(::Protobuf::Message)
         
     | 
| 
         @@ -132,16 +52,5 @@ module Protoable 
     | 
|
| 
       132 
52 
     | 
    
         | 
| 
       133 
53 
     | 
    
         
             
                  super(attributes, options)
         
     | 
| 
       134 
54 
     | 
    
         
             
                end
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
                # Update a record from a proto message. Accepts an optional block.
         
     | 
| 
       137 
     | 
    
         
            -
                # If block is given, yields the attributes that would be updated.
         
     | 
| 
       138 
     | 
    
         
            -
                #
         
     | 
| 
       139 
     | 
    
         
            -
                def update_from_proto(proto, options = {})
         
     | 
| 
       140 
     | 
    
         
            -
                  attributes = attributes_from_proto(proto)
         
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                  yield(attributes) if block_given?
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
                  update_attributes(attributes, options)
         
     | 
| 
       145 
     | 
    
         
            -
                end
         
     | 
| 
       146 
55 
     | 
    
         
             
              end
         
     | 
| 
       147 
56 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,7 +4,6 @@ module Protoable 
     | 
|
| 
       4 
4 
     | 
    
         
             
                  klass.class_eval do
         
     | 
| 
       5 
5 
     | 
    
         
             
                    class << self
         
     | 
| 
       6 
6 
     | 
    
         
             
                      alias_method :by_fields, :search_scope
         
     | 
| 
       7 
     | 
    
         
            -
                      alias_method :from_proto, :search_scope
         
     | 
| 
       8 
7 
     | 
    
         
             
                      alias_method :scope_from_proto, :search_scope
         
     | 
| 
       9 
8 
     | 
    
         
             
                    end
         
     | 
| 
       10 
9 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -34,7 +33,6 @@ module Protoable 
     | 
|
| 
       34 
33 
     | 
    
         
             
                #   # Search starting with the default scope and searchable fields
         
     | 
| 
       35 
34 
     | 
    
         
             
                #   User.search_scope(request)
         
     | 
| 
       36 
35 
     | 
    
         
             
                #   User.by_fields(request)
         
     | 
| 
       37 
     | 
    
         
            -
                #   User.from_proto(request)
         
     | 
| 
       38 
36 
     | 
    
         
             
                #   User.scope_from_proto(request)
         
     | 
| 
       39 
37 
     | 
    
         
             
                #
         
     | 
| 
       40 
38 
     | 
    
         
             
                def search_scope(proto)
         
     | 
| 
         @@ -8,20 +8,38 @@ module Protoable 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  klass.class_eval do
         
     | 
| 
       10 
10 
     | 
    
         
             
                    class << self
         
     | 
| 
       11 
     | 
    
         
            -
                      attr_accessor : 
     | 
| 
       12 
     | 
    
         
            -
                        :_protobuf_field_transformers, :protobuf_fields
         
     | 
| 
      
 11 
     | 
    
         
            +
                      attr_accessor :_protobuf_field_transformers, :_protobuf_field_options
         
     | 
| 
       13 
12 
     | 
    
         
             
                    end
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                    @_protobuf_attribute_converters = {}
         
     | 
| 
       16 
14 
     | 
    
         
             
                    @_protobuf_field_transformers = {}
         
     | 
| 
       17 
     | 
    
         
            -
                    @ 
     | 
| 
      
 15 
     | 
    
         
            +
                    @_protobuf_field_options = {}
         
     | 
| 
       18 
16 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                    inheritable_attributes : 
     | 
| 
       20 
     | 
    
         
            -
                      : 
     | 
| 
      
 17 
     | 
    
         
            +
                    inheritable_attributes :_protobuf_field_transformers, :_protobuf_field_options,
         
     | 
| 
      
 18 
     | 
    
         
            +
                      :protobuf_message
         
     | 
| 
       21 
19 
     | 
    
         
             
                  end
         
     | 
| 
       22 
20 
     | 
    
         
             
                end
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
       24 
22 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # :nodoc:
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def _protobuf_convert_attributes_to_fields(key, value)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    return value if value.nil?
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    value = case
         
     | 
| 
      
 28 
     | 
    
         
            +
                            when _protobuf_date_column?(key) then
         
     | 
| 
      
 29 
     | 
    
         
            +
                              value.to_time.to_i
         
     | 
| 
      
 30 
     | 
    
         
            +
                            when _protobuf_datetime_column?(key) then
         
     | 
| 
      
 31 
     | 
    
         
            +
                              value.to_i
         
     | 
| 
      
 32 
     | 
    
         
            +
                            when _protobuf_time_column?(key) then
         
     | 
| 
      
 33 
     | 
    
         
            +
                              value.to_i
         
     | 
| 
      
 34 
     | 
    
         
            +
                            when _protobuf_timestamp_column?(key) then
         
     | 
| 
      
 35 
     | 
    
         
            +
                              value.to_i
         
     | 
| 
      
 36 
     | 
    
         
            +
                            else
         
     | 
| 
      
 37 
     | 
    
         
            +
                              value
         
     | 
| 
      
 38 
     | 
    
         
            +
                            end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    return value
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       25 
43 
     | 
    
         
             
                  # Define a field transformation from a record. Accepts a Symbol,
         
     | 
| 
       26 
44 
     | 
    
         
             
                  # callable, or block that is called with the record being serialized.
         
     | 
| 
       27 
45 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -39,8 +57,8 @@ module Protoable 
     | 
|
| 
       39 
57 
     | 
    
         
             
                  #     # Do some blocky stuff...
         
     | 
| 
       40 
58 
     | 
    
         
             
                  #   end
         
     | 
| 
       41 
59 
     | 
    
         
             
                  #
         
     | 
| 
       42 
     | 
    
         
            -
                  def field_from_record(field, transformer = nil, & 
     | 
| 
       43 
     | 
    
         
            -
                    transformer ||=  
     | 
| 
      
 60 
     | 
    
         
            +
                  def field_from_record(field, transformer = nil, &block)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    transformer ||= block
         
     | 
| 
       44 
62 
     | 
    
         | 
| 
       45 
63 
     | 
    
         
             
                    if transformer.is_a?(Symbol)
         
     | 
| 
       46 
64 
     | 
    
         
             
                      callable = lambda { |value| self.__send__(transformer, value) }
         
     | 
| 
         @@ -55,68 +73,37 @@ module Protoable 
     | 
|
| 
       55 
73 
     | 
    
         
             
                    _protobuf_field_transformers[field.to_sym] = callable
         
     | 
| 
       56 
74 
     | 
    
         
             
                  end
         
     | 
| 
       57 
75 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                  # Define a custom attribute conversion for serialization to protobuf.
         
     | 
| 
       59 
     | 
    
         
            -
                  # Accepts a Symbol, Hash, callable or block.
         
     | 
| 
       60 
     | 
    
         
            -
                  #
         
     | 
| 
       61 
     | 
    
         
            -
                  # When given a callable or block, it is directly used to convert the field.
         
     | 
| 
       62 
     | 
    
         
            -
                  #
         
     | 
| 
       63 
     | 
    
         
            -
                  # When a Hash is given, :from and :to keys are expected and expand
         
     | 
| 
       64 
     | 
    
         
            -
                  # to extracting a class method in the format of
         
     | 
| 
       65 
     | 
    
         
            -
                  # "convert_#{from}_to_#{to}".
         
     | 
| 
       66 
     | 
    
         
            -
                  #
         
     | 
| 
       67 
     | 
    
         
            -
                  # When a symbol is given, it extracts the method with the same name.
         
     | 
| 
       68 
     | 
    
         
            -
                  #
         
     | 
| 
       69 
     | 
    
         
            -
                  # Examples:
         
     | 
| 
       70 
     | 
    
         
            -
                  #   protoable_attribute :public_key, :extract_public_key_from_proto
         
     | 
| 
       71 
     | 
    
         
            -
                  #   protoable_attribute :symmetric_key, :from => :base64, :to => :raw_string
         
     | 
| 
       72 
     | 
    
         
            -
                  #   protoable_attribute :status, lambda { |proto_field| # Do stuff... }
         
     | 
| 
       73 
     | 
    
         
            -
                  #   protoable_attribute :status do |proto_field|
         
     | 
| 
       74 
     | 
    
         
            -
                  #     # Do some blocky stuff...
         
     | 
| 
       75 
     | 
    
         
            -
                  #   end
         
     | 
| 
       76 
     | 
    
         
            -
                  #
         
     | 
| 
       77 
     | 
    
         
            -
                  def protoable_attribute(field, converter = nil, &blk)
         
     | 
| 
       78 
     | 
    
         
            -
                    converter ||= blk
         
     | 
| 
       79 
     | 
    
         
            -
                    converter = :"convert_#{converter[:from]}_to_#{converter[:to]}" if converter.is_a?(Hash)
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                    if converter.is_a?(Symbol)
         
     | 
| 
       82 
     | 
    
         
            -
                      callable = lambda { |value| __send__(converter, value) }
         
     | 
| 
       83 
     | 
    
         
            -
                    else
         
     | 
| 
       84 
     | 
    
         
            -
                      callable = converter
         
     | 
| 
       85 
     | 
    
         
            -
                    end
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                    unless callable.respond_to?(:call)
         
     | 
| 
       88 
     | 
    
         
            -
                      raise AttributeConverterError, 'Attribute converters must be a callable or block!'
         
     | 
| 
       89 
     | 
    
         
            -
                    end
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
                    _protobuf_attribute_converters[field.to_sym] = callable
         
     | 
| 
       92 
     | 
    
         
            -
                  end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
76 
     | 
    
         
             
                  # Define the protobuf message class that should be used to serialize the
         
     | 
| 
       95 
     | 
    
         
            -
                  # object to protobuf. Accepts a string or symbol.
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # object to protobuf. Accepts a string or symbol and an options hash.
         
     | 
| 
       96 
78 
     | 
    
         
             
                  #
         
     | 
| 
       97 
79 
     | 
    
         
             
                  # When protobuf_message is declared, Protoable automatically extracts the
         
     | 
| 
       98 
     | 
    
         
            -
                  # fields from the message and automatically adds to_proto  
     | 
| 
       99 
     | 
    
         
            -
                  #  
     | 
| 
      
 80 
     | 
    
         
            +
                  # fields from the message and automatically adds a to_proto method that
         
     | 
| 
      
 81 
     | 
    
         
            +
                  # serializes the object to protobuf.
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #
         
     | 
| 
      
 83 
     | 
    
         
            +
                  # The fields that will be automatically serialized can be configured by
         
     | 
| 
      
 84 
     | 
    
         
            +
                  # passing :only or :except in the options hash. If :only is specified, only
         
     | 
| 
      
 85 
     | 
    
         
            +
                  # the specified fields will be serialized. If :except is specified, all
         
     | 
| 
      
 86 
     | 
    
         
            +
                  # field except the specified fields will be serialized.
         
     | 
| 
      
 87 
     | 
    
         
            +
                  #
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # By default, deprecated fields will be serialized. To exclude deprecated
         
     | 
| 
      
 89 
     | 
    
         
            +
                  # fields, pass :deprecated => false in the options hash.
         
     | 
| 
       100 
90 
     | 
    
         
             
                  #
         
     | 
| 
       101 
91 
     | 
    
         
             
                  # Examples:
         
     | 
| 
       102 
92 
     | 
    
         
             
                  #   protobuf_message :user_message
         
     | 
| 
       103 
93 
     | 
    
         
             
                  #   protobuf_message "UserMessage"
         
     | 
| 
       104 
94 
     | 
    
         
             
                  #   protobuf_message "Namespaced::UserMessage"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  #   protobuf_message :user_message, :only => :guid, :name
         
     | 
| 
      
 96 
     | 
    
         
            +
                  #   protobuf_message :user_message, :except => :email_domain
         
     | 
| 
      
 97 
     | 
    
         
            +
                  #   protobuf_message :user_message, :except => :email_domain, :deprecated => false
         
     | 
| 
       105 
98 
     | 
    
         
             
                  #
         
     | 
| 
       106 
     | 
    
         
            -
                  def protobuf_message(message = nil)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  def protobuf_message(message = nil, options = {})
         
     | 
| 
       107 
100 
     | 
    
         
             
                    unless message.nil?
         
     | 
| 
       108 
101 
     | 
    
         
             
                      @protobuf_message = message.to_s.classify.constantize
         
     | 
| 
       109 
102 
     | 
    
         | 
| 
       110 
     | 
    
         
            -
                      self. 
     | 
| 
       111 
     | 
    
         
            -
                        field.name.to_sym
         
     | 
| 
       112 
     | 
    
         
            -
                      end
         
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
                      define_method(:to_proto) do
         
     | 
| 
       115 
     | 
    
         
            -
                        self.class.protobuf_message.new(self.to_proto_hash)
         
     | 
| 
       116 
     | 
    
         
            -
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                      self._protobuf_field_options = options
         
     | 
| 
       117 
104 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                      define_method(: 
     | 
| 
       119 
     | 
    
         
            -
                         
     | 
| 
      
 105 
     | 
    
         
            +
                      define_method(:to_proto) do |options = {}|
         
     | 
| 
      
 106 
     | 
    
         
            +
                        self.class.protobuf_message.new(self.fields_from_record(options))
         
     | 
| 
       120 
107 
     | 
    
         
             
                      end
         
     | 
| 
       121 
108 
     | 
    
         
             
                    end
         
     | 
| 
       122 
109 
     | 
    
         | 
| 
         @@ -124,11 +111,51 @@ module Protoable 
     | 
|
| 
       124 
111 
     | 
    
         
             
                  end
         
     | 
| 
       125 
112 
     | 
    
         
             
                end
         
     | 
| 
       126 
113 
     | 
    
         | 
| 
      
 114 
     | 
    
         
            +
                # :nodoc:
         
     | 
| 
      
 115 
     | 
    
         
            +
                def _filter_field_attributes(options = {})
         
     | 
| 
      
 116 
     | 
    
         
            +
                  options = _normalize_options(options)
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  fields = _filtered_fields(options)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  fields &= [ options[:only] ].flatten if options[:only].present?
         
     | 
| 
      
 120 
     | 
    
         
            +
                  fields -= [ options[:except] ].flatten if options[:except].present?
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  fields
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                # :nodoc:
         
     | 
| 
      
 126 
     | 
    
         
            +
                def _filtered_fields(options = {})
         
     | 
| 
      
 127 
     | 
    
         
            +
                  exclude_deprecated = ! options.fetch(:deprecated, true)
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  fields = self.class.protobuf_message.fields.map do |field|
         
     | 
| 
      
 130 
     | 
    
         
            +
                    next if field.nil?
         
     | 
| 
      
 131 
     | 
    
         
            +
                    next if exclude_deprecated && field.deprecated?
         
     | 
| 
      
 132 
     | 
    
         
            +
                    field.name.to_sym
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                  fields.compact!
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  fields
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                # :nodoc:
         
     | 
| 
      
 140 
     | 
    
         
            +
                def _normalize_options(options)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  options ||= {}
         
     | 
| 
      
 142 
     | 
    
         
            +
                  options[:only] ||= [] if options.fetch(:except, false)
         
     | 
| 
      
 143 
     | 
    
         
            +
                  options[:except] ||= [] if options.fetch(:only, false)
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                  self.class._protobuf_field_options.merge(options)
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
       127 
148 
     | 
    
         
             
                # Extracts attributes that correspond to fields on the specified protobuf
         
     | 
| 
       128 
149 
     | 
    
         
             
                # message, performing any necessary column conversions on them.
         
     | 
| 
       129 
150 
     | 
    
         
             
                #
         
     | 
| 
       130 
     | 
    
         
            -
                def  
     | 
| 
       131 
     | 
    
         
            -
                   
     | 
| 
      
 151 
     | 
    
         
            +
                def fields_from_record(options = {})
         
     | 
| 
      
 152 
     | 
    
         
            +
                  field_attributes = _filter_field_attributes(options)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  field_attributes += [ options.fetch(:include, []) ]
         
     | 
| 
      
 154 
     | 
    
         
            +
                  field_attributes.flatten!
         
     | 
| 
      
 155 
     | 
    
         
            +
                  field_attributes.compact
         
     | 
| 
      
 156 
     | 
    
         
            +
                  field_attributes.uniq!
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  field_attributes = field_attributes.inject({}) do |hash, field|
         
     | 
| 
       132 
159 
     | 
    
         
             
                    if _protobuf_field_transformers.has_key?(field)
         
     | 
| 
       133 
160 
     | 
    
         
             
                      hash[field] = _protobuf_field_transformers[field].call(self)
         
     | 
| 
       134 
161 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -138,7 +165,7 @@ module Protoable 
     | 
|
| 
       138 
165 
     | 
    
         
             
                    hash
         
     | 
| 
       139 
166 
     | 
    
         
             
                  end
         
     | 
| 
       140 
167 
     | 
    
         | 
| 
       141 
     | 
    
         
            -
                   
     | 
| 
      
 168 
     | 
    
         
            +
                  field_attributes
         
     | 
| 
       142 
169 
     | 
    
         
             
                end
         
     | 
| 
       143 
170 
     | 
    
         | 
| 
       144 
171 
     | 
    
         
             
              private
         
     | 
| 
         @@ -150,9 +177,5 @@ module Protoable 
     | 
|
| 
       150 
177 
     | 
    
         
             
                def _protobuf_field_transformers
         
     | 
| 
       151 
178 
     | 
    
         
             
                  self.class._protobuf_field_transformers
         
     | 
| 
       152 
179 
     | 
    
         
             
                end
         
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
                def protobuf_fields
         
     | 
| 
       155 
     | 
    
         
            -
                  self.class.protobuf_fields
         
     | 
| 
       156 
     | 
    
         
            -
                end
         
     | 
| 
       157 
180 
     | 
    
         
             
              end
         
     | 
| 
       158 
181 
     | 
    
         
             
            end
         
     |