Module: Protobuf::ActiveRecord::Transformation::ClassMethods

Defined in:
lib/protobuf/active_record/transformation.rb

Instance Method Summary collapse

Instance Method Details

#_filter_attribute_fields(proto) ⇒ Object

Filters accessible attributes that exist in the given protobuf message’s fields or have attribute transformers defined for them.

Returns a hash of attribute fields with their respective values.

:nodoc:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/protobuf/active_record/transformation.rb', line 29

def _filter_attribute_fields(proto)
  fields = proto.to_hash
  fields.select! do |key, _value|
    field = proto.class.get_field(key, true)
    proto.field?(key) && !field.repeated?
  end

  filtered_attributes = _filtered_attributes + _protobuf_attribute_transformers.keys

  attribute_fields = filtered_attributes.each_with_object({}) do |column_name, hash|
    symbolized_column = column_name.to_sym

    if fields.key?(symbolized_column) || _protobuf_attribute_transformers.key?(symbolized_column)
      hash[symbolized_column] = fields[symbolized_column]
    end
  end

  _protobuf_nested_attributes.each do |attribute_name|
    nested_attribute_name = :"#{attribute_name}_attributes"
    value = if proto.field?(nested_attribute_name)
      proto.__send__(nested_attribute_name)
    elsif proto.field?(attribute_name)
      proto.__send__(attribute_name)
    end

    next unless value
    attribute_fields[nested_attribute_name] = value
  end

  attribute_fields
end

#_filtered_attributesObject

Overidden by mass assignment security when protected attributes is loaded.

:nodoc:



64
65
66
# File 'lib/protobuf/active_record/transformation.rb', line 64

def _filtered_attributes
  attribute_names
end

#_protobuf_convert_fields_to_attributes(key, value) ⇒ Object

:nodoc:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/protobuf/active_record/transformation.rb', line 69

def _protobuf_convert_fields_to_attributes(key, value)
  return nil if value.nil?
  return value unless _protobuf_date_datetime_time_or_timestamp_column?(key)

  if _protobuf_datetime_column?(key)

    convert_int64_to_datetime(value)
  elsif _protobuf_timestamp_column?(key)

    convert_int64_to_time(value)
  elsif _protobuf_time_column?(key)

    convert_int64_to_time(value)
  elsif _protobuf_date_column?(key)

    convert_int64_to_date(value)
  end
end

#attribute_from_proto(attribute, *args, &block) ⇒ Object

Define an attribute transformation from protobuf. Accepts a Symbol, callable, or block.

When given a callable or block, it is directly used to convert the field.

When a symbol is given, it extracts the method with the same name.

The callable or method must accept a single parameter, which is the proto message.

Examples:

attribute_from_proto :public_key, :extract_public_key_from_proto
attribute_from_proto :status, lambda { |proto| # Do some stuff... }
attribute_from_proto :status do |proto|
  # Do some blocky stuff...
end

attribute_from_proto :status, lambda { |proto| nil }, :nullify_on => :status
attribute_from_proto :status, :nullify_on => :status do |proto|
  nil
end


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/protobuf/active_record/transformation.rb', line 110

def attribute_from_proto(attribute, *args, &block)
  options = args.extract_options!
  symbol_or_block = args.first || block

  if symbol_or_block.is_a?(Symbol)
    callable = lambda { |value| __send__(symbol_or_block, value) }
  else
    raise AttributeTransformerError unless symbol_or_block.respond_to?(:call)
    callable = symbol_or_block
  end

  if options[:nullify_on]
    field = protobuf_message.get_field(:nullify)
    unless field&.is_a?(::Protobuf::Field::StringField) && field&.repeated?
      ::Protobuf::Logging.logger.warn "Message: #{protobuf_message} is not compatible with :nullify_on option"
    end
  end

  transformer = ::Protobuf::ActiveRecord::Transformer.new(callable, options)
  _protobuf_attribute_transformers[attribute.to_sym] = transformer
end

#attributes_from_proto(proto) ⇒ Object

Creates a hash of attributes from a given protobuf message.

It converts and transforms field values using the field converters and attribute transformers, ignoring repeated and nil fields.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/protobuf/active_record/transformation.rb', line 137

def attributes_from_proto(proto)
  attribute_fields = _filter_attribute_fields(proto)

  attributes = attribute_fields.each_with_object({}) do |(key, value), hash|
    if _protobuf_attribute_transformers.key?(key)
      transformer = _protobuf_attribute_transformers[key]
      attribute = transformer.call(proto)
      hash[key] = attribute unless attribute.nil?
      hash[key] = nil if transformer.nullify?(proto)
    else
      hash[key] = _protobuf_convert_fields_to_attributes(key, value)
    end
  end

  return attributes unless proto.field?(:nullify) && proto.nullify.is_a?(Array)

  proto.nullify.each do |attribute_name|
    attributes[attribute_name.to_sym] = nil if attribute_names.include?(attribute_name.to_s)
  end

  attributes
end

#convert_int64_to_date(int64) ⇒ Object

:nodoc:



166
167
168
# File 'lib/protobuf/active_record/transformation.rb', line 166

def convert_int64_to_date(int64)
  convert_int64_to_time(int64).utc.to_date
end

#convert_int64_to_datetime(int64) ⇒ Object

:nodoc:



171
172
173
# File 'lib/protobuf/active_record/transformation.rb', line 171

def convert_int64_to_datetime(int64)
  convert_int64_to_time(int64).to_datetime
end

#convert_int64_to_time(int64) ⇒ Object

:nodoc:



161
162
163
# File 'lib/protobuf/active_record/transformation.rb', line 161

def convert_int64_to_time(int64)
  Time.at(int64.to_i)
end