class FieldMaskedModel::Base
Attributes
inaccessible_error_callback[R]
model_pool[R]
msg[R]
Public Class Methods
dispatch(entry)
click to toggle source
@param [Google::Protobuf::FieldDescriptor] entry @return [Symbol]
# File lib/field_masked_model/base.rb, line 76 def dispatch(entry) case entry.type when :message m = @model_pool.lookup(entry.subtype.msgclass) # NOTE: If msgclass is not registered in ModelPool, we treat it # as a one of attribute classes. if m.nil? return :attribute end case entry.label when :repeated :repeated_association else :association end else # eum or scalar :attribute end end
entries()
click to toggle source
@return [<Google::Protobuf::FieldDescriptor>]
# File lib/field_masked_model/base.rb, line 68 def entries @msg.descriptor.entries.select do |e| !_excluded_fields.include?(e.name) end end
exclude_field(name)
click to toggle source
@param [Symbol, String] name
# File lib/field_masked_model/base.rb, line 33 def exclude_field(name) if defined?(@msg) Kernel.warn("exclude_field must be called before msgclass", uplevel: 1) end _excluded_fields << name.to_s end
fields()
click to toggle source
@return [<Symbol, { Symbol => Array }>]
# File lib/field_masked_model/base.rb, line 46 def fields r = [] children = {} self.entries.each do |entry| n = entry.name.to_sym type = self.dispatch(entry) case type when :attribute r << n when :association modelclass = @model_pool.lookup(entry.subtype.msgclass) children[n] = modelclass.fields when :repeated_association modelclass = @model_pool.lookup(entry.subtype.msgclass) children[n] = modelclass.fields end end r << children if children.size > 0 r end
msgclass(klass, exclude_fields: [], model_pool: ModelPool.generated_pool)
click to toggle source
@param [Class] klass A class represents the protobuf message class @param [<Symbol, String>] exclude_fields @param [FieldMaskedModel::ModelPool] model_pool
# File lib/field_masked_model/base.rb, line 16 def msgclass(klass, exclude_fields: [], model_pool: ModelPool.generated_pool) if defined?(@msg) raise "msgclass is already registered!" end @model_pool = model_pool @model_pool.add(klass, self) exclude_fields.each do |field| exclude_field field end @msg = klass define_accessors! end
new(field_mask: nil, field_mask_node: nil, message:)
click to toggle source
@param [Google::Protobuf::FieldMask, nil] field_mask_node @param [FMParser::MessageNode, nil] field_mask_node @param [Object] message represents the protobuf message object
# File lib/field_masked_model/base.rb, line 151 def initialize(field_mask: nil, field_mask_node: nil, message:) if field_mask.nil? && field_mask_node.nil? raise ArgumentError.new("missing keyword: field_mask or field_mask_node") end @fm_node = field_mask_node || FMParser.parse(paths: field_mask.paths, root: self.class.msg) @message = message @accessible_fields ||= Set.new(@fm_node.field_names) end
set_inaccessible_error_callback(callback)
click to toggle source
@param [Proc] callback
# File lib/field_masked_model/base.rb, line 41 def set_inaccessible_error_callback(callback) @inaccessible_error_callback = callback end
Private Class Methods
_excluded_fields()
click to toggle source
# File lib/field_masked_model/base.rb, line 143 def _excluded_fields @_excluded_fields ||= Set.new end
define_accessor!(name:, entry:)
click to toggle source
# File lib/field_masked_model/base.rb, line 106 def define_accessor!(name:, entry:) define_method(name) do validate!(name) ivar = :"@_#{name}" if instance_variable_defined?(ivar) next instance_variable_get(ivar) end v = @message.send(name) type = self.class.dispatch(entry) r = case type when :attribute AttributeConverter.convert(v) when :association if v.nil? nil else modelclass = self.class.model_pool.lookup(entry.subtype.msgclass) modelclass.new(field_mask_node: @fm_node.get_child(name), message: v) end when :repeated_association modelclass = self.class.model_pool.lookup(entry.subtype.msgclass) v.map do |vv| if vv.nil? nil else modelclass.new(field_mask_node: @fm_node.get_child(name), message: vv) end end end instance_variable_set(ivar, r) end end
define_accessors!()
click to toggle source
# File lib/field_masked_model/base.rb, line 99 def define_accessors! self.entries.each do |entry| n = entry.name.to_sym define_accessor!(name: n, entry: entry) end end
Public Instance Methods
inspect()
click to toggle source
@return [String]
# File lib/field_masked_model/base.rb, line 187 def inspect h = {} self.class.entries.each do |entry| n = entry.name.to_sym if !@accessible_fields.include?(n) h[n] = "-" next end v = self.send(n) type = self.class.dispatch(entry) case type when :attribute case v when NilClass h[n] = "nil" when String h[n] = "\"#{v}\"" else h[n] = v end when :association case v when NilClass h[n] = "nil" else h[n] = v.class.name.split("::").last end when :repeated_association if v.size > 0 h[n] = "[#{v[0].class.name.split("::").last}]" else h[n] = "[]" end end end "<#{self.class.name}#{h.map { |k, v| "\n #{k}: #{v}" }.join(',')}>" end
to_h()
click to toggle source
@return [Hash]
# File lib/field_masked_model/base.rb, line 162 def to_h r = {} self.class.entries.each do |entry| n = entry.name.to_sym next if !@accessible_fields.include?(n) v = self.send(n) type = self.class.dispatch(entry) case type when :attribute r[n] = v when :association if v.nil? r[n] = nil else r[n] = v.to_h end when :repeated_association r[n] = v.map(&:to_h) end end r end
Private Instance Methods
validate!(field)
click to toggle source
@param [Symbol] field @raise [FieldMaskedModel::InaccessibleError]
# File lib/field_masked_model/base.rb, line 230 def validate!(field) if !@accessible_fields.include?(field) if self.class.inaccessible_error_callback self.class.inaccessible_error_callback.call(field) else raise FieldMaskedModel::InaccessibleError.new("`#{field}` is not specified as paths in field_mask!") end end end