Module: Serega::ClassMethods

Included in:
Serega
Defined in:
lib/serega.rb

Overview

Serializers class methods

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#configSeregaConfig (readonly)

Returns current config

Returns:



104
105
106
# File 'lib/serega.rb', line 104

def config
  @config
end

Instance Method Details

#attribute(name, **opts, &block) ⇒ Serega::SeregaAttribute

Adds attribute

Patched in:

  • plugin :presenter (additionally adds method in Presenter class)

Parameters:

  • name (Symbol)

    Attribute name. Attribute value will be found by executing object.<name>

  • opts (Hash)

    Options to serialize attribute

  • block (Proc)

    Custom block to find attribute value. Accepts object and context.

Returns:



180
181
182
183
# File 'lib/serega.rb', line 180

def attribute(name, **opts, &block)
  attribute = self::SeregaAttribute.new(name: name, opts: opts, block: block)
  attributes[attribute.name] = attribute
end

#attributesHash

Lists attributes

Returns:

  • (Hash)

    attributes list



155
156
157
# File 'lib/serega.rb', line 155

def attributes
  @attributes ||= {}
end

#batch(name, value = nil, &block) ⇒ #call

Defines a batch loader

Examples:

batch :tags, PostTagsLoader

with block

batch_loader(:tags) do |posts|
  Tags.where(post: posts).group(:post_id).pluck(:post_id, Arel.sql('ARRAY_AGG(tags.tag ORDER BY tag)')).to_h
end

attribute :tags, batch: :tags, value: { |post, batch:| batch[:tags][post.id] }

with context

batch_loader(:tags) do |posts, ctx:|
  next {} if ctx[:bot]

  Tags.where(post: posts).group(:post_id).pluck(:post_id, Arel.sql('ARRAY_AGG(tags.tag ORDER BY tag)')).to_h
end

attribute :tags, batch: :tags, value: { |post, batch:| batch[:tags][post.id] }

Parameters:

  • name (Symbol)

    A batch loader name

  • value (#call) (defaults to: nil)

    Batch loader

  • block (Proc)

    Batch loader

Returns:

  • (#call)

    Batch loader

Raises:



213
214
215
216
217
218
# File 'lib/serega.rb', line 213

def batch(name, value = nil, &block)
  raise SeregaError, "Batch loader must be defined with a callable value or block" if (value && block) || (!value && !block)

  batch_loader = self::SeregaBatchLoader.new(name: name, block: value || block)
  batch_loaders[batch_loader.name] = batch_loader
end

#batch_loadersHash

Lists defined batch loaders

Returns:

  • (Hash)

    batch loaders list



164
165
166
# File 'lib/serega.rb', line 164

def batch_loaders
  @batch_loaders ||= {}
end

#call(object, opts = nil) ⇒ Hash Also known as: to_h

Serializes provided object to Hash

Parameters:

  • object (Object)

    Serialized object

  • opts (Hash, nil) (defaults to: nil)

    Serializer modifiers and other instantiating options

Options Hash (opts):

  • :only (Array, Hash, String, Symbol)

    The only attributes to serialize

  • :except (Array, Hash, String, Symbol)

    Attributes to hide

  • :with (Array, Hash, String, Symbol)

    Attributes (usually hidden) to serialize additionally

  • :validate (Boolean)

    Validates provided modifiers (Default is true)

  • :context (Hash)

    Serialization context

  • :many (Boolean)

    Set true if provided multiple objects (Default object.is_a?(Enumerable))

Returns:

  • (Hash)

    Serialization result



266
267
268
269
270
271
# File 'lib/serega.rb', line 266

def call(object, opts = nil)
  opts = opts&.transform_keys(&:to_sym)
  modifiers_opts = init_modifier_opts(opts)
  serialize_opts = init_serialize_opts(opts)
  new(modifiers_opts).to_h(object, serialize_opts)
end

#plugin(name, **opts) ⇒ class<Module>

Enables plugin for current serializer

Parameters:

  • name (Symbol, Class<Module>)

    Plugin name or plugin module itself

  • opts (Hash)

    ] Plugin options

Returns:

  • (class<Module>)

    Loaded plugin module

Raises:



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/serega.rb', line 113

def plugin(name, **opts)
  raise SeregaError, "This plugin is already loaded" if plugin_used?(name)

  plugin = SeregaPlugins.find_plugin(name)

  # We split loading of plugin to three parts - before_load, load, after_load:
  #
  # - **before_load_plugin** usually used to check requirements and to load additional plugins
  # - **load_plugin** usually used to include plugin modules
  # - **after_load_plugin** usually used to add config options
  plugin.before_load_plugin(self, **opts) if plugin.respond_to?(:before_load_plugin)
  plugin.load_plugin(self, **opts) if plugin.respond_to?(:load_plugin)
  plugin.after_load_plugin(self, **opts) if plugin.respond_to?(:after_load_plugin)

  # Store attached plugins, so we can check it is loaded later
  config.plugins << (plugin.respond_to?(:plugin_name) ? plugin.plugin_name : plugin)

  plugin
end

#plugin_used?(name) ⇒ Boolean

Checks plugin is used

Parameters:

  • name (Symbol, Class<Module>)

    Plugin name or plugin module itself

Returns:

  • (Boolean)

    Is plugin used



140
141
142
143
144
145
146
147
148
# File 'lib/serega.rb', line 140

def plugin_used?(name)
  plugin_name =
    case name
    when Module then name.respond_to?(:plugin_name) ? name.plugin_name : name
    else name
    end

  config.plugins.include?(plugin_name)
end

#preload_with(value = nil, &block) ⇒ #call?

Registers (or returns) the handler used to preload an attribute's associations onto the records gathered during serialization.

The handler is called once per preloaded attribute with the gathered objects and that attribute's preloads. ORM plugins register a handler that performs the actual eager loading.

Examples:

with a block

preload_with { |objects, preloads| MyORM.eager_load(objects, preloads) }

with a callable value

preload_with MyPreloader

Parameters:

  • value (#call, nil) (defaults to: nil)

    Preload handler accepting two positional arguments

  • block (Proc)

    Preload handler accepting two positional arguments

Returns:

  • (#call, nil)

    The registered preload handler

Raises:



239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/serega.rb', line 239

def preload_with(value = nil, &block)
  return @preload_with if value.nil? && block.nil?
  raise SeregaError, "preload_with accepts a single callable or a block, not both" if value && block

  handler = value || block
  raise SeregaError, "preload_with value must be a Proc or respond to #call" if !handler.is_a?(Proc) && !handler.respond_to?(:call)

  signature = SeregaUtils::MethodSignature.call(handler, pos_limit: 2)
  raise SeregaError, "preload_with handler must accept two positional arguments: (objects, preloads)" unless signature == "2"

  @preload_with = handler
end

#to_data(object, opts = nil) ⇒ Data, ...

Serializes provided object to a tree of Ruby Data objects

Parameters:

  • object (Object)

    Serialized object

  • opts (Hash, nil) (defaults to: nil)

    Serializer modifiers and other instantiating options

Options Hash (opts):

  • :only (Array, Hash, String, Symbol)

    The only attributes to serialize

  • :except (Array, Hash, String, Symbol)

    Attributes to hide

  • :with (Array, Hash, String, Symbol)

    Attributes (usually hidden) to serialize additionally

  • :validate (Boolean)

    Validates provided modifiers (Default is true)

  • :context (Hash)

    Serialization context

  • :many (Boolean)

    Set true if provided multiple objects (Default object.is_a?(Enumerable))

Returns:

  • (Data, Array<Data>, nil)

    Serialization result as Data object(s)



287
288
289
290
291
292
# File 'lib/serega.rb', line 287

def to_data(object, opts = nil)
  opts = opts&.transform_keys(&:to_sym)
  modifiers_opts = init_modifier_opts(opts)
  serialize_opts = init_serialize_opts(opts)
  new(modifiers_opts).to_data(object, serialize_opts)
end