Module: Serega::SeregaPlugins::Batch

Defined in:
lib/serega/plugins/batch/batch.rb,
lib/serega/plugins/batch/lib/loader.rb,
lib/serega/plugins/batch/lib/loaders.rb,
lib/serega/plugins/batch/lib/batch_config.rb,
lib/serega/plugins/batch/lib/modules/config.rb,
lib/serega/plugins/batch/lib/modules/attribute.rb,
lib/serega/plugins/batch/lib/modules/plan_point.rb,
lib/serega/plugins/batch/lib/modules/object_serializer.rb,
lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb,
lib/serega/plugins/batch/lib/validations/check_opt_batch.rb,
lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb,
lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb,
lib/serega/plugins/batch/lib/modules/check_attribute_params.rb,
lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb,
lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb,
lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb

Overview

Plugin ‘:batch`

Adds ability to load nested attributes values in batches.

It can be used to find value for attributes in optimal way:

  • load associations for multiple objects

  • load counters for multiple objects

  • make any heavy calculations for multiple objects only once

After including plugin, attributes gain new ‘:batch` option.

‘:batch` option must be a hash with this keys:

  • ‘key` (required) [Symbol, Proc, callable] - Defines current object identifier. Later `loader` will accept array of `keys` to find `values`.

  • ‘loader` (required) [Symbol, Proc, callable] - Defines how to fetch values for batch of keys. Receives 3 parameters: keys, context, plan_point.

  • ‘default` (optional) - Default value for attribute. By default it is `nil` or `[]` when attribute has option `many: true`

If ‘:loader` was defined using name (as Symbol) then batch loader must be defined in serializer config: `config.batch.define(:loader_name) { … }` method.

*Result of this ‘:loader` callable must be a Hash where*:

  • keys - provided keys

  • values - values for according keys

‘Batch` plugin can be defined with two specific attributes:

  • ‘auto_hide: true` - Marks attributes with defined :batch as hidden, so it will not be serialized by default

  • ‘default_key: :id` - Set default object key (in this case :id) that will be used for all attributes with :batch option specified.

This options (‘auto_hide`, `default_key`) also can be set as config options in any nested serializer.

Examples:

class PostSerializer < Serega
  plugin :batch, auto_hide: true, default_key: :id

  # Define batch loader via callable class, it must accept three args (keys, context, plan_point)
  attribute :comments_count, batch: { loader: PostCommentsCountBatchLoader, default: 0}

  # Define batch loader via Symbol, later we should define this loader via config.batch.define(:posts_comments_counter) { ... }
  attribute :comments_count, batch: { loader: :posts_comments_counter, default: 0}

  # Define batch loader with serializer
  attribute :comments, serializer: CommentSerializer, batch: { loader: :posts_comments, default: []}

  # Resulted block must return hash like { key => value(s) }
  config.batch.define(:posts_comments_counter) do |keys|
    Comment.group(:post_id).where(post_id: keys).count
  end

  # We can return objects that will be automatically serialized if attribute defined with :serializer
  # Parameter `context` can be used when loading batch
  # Parameter `plan_point` can be used to find nested attributes that will be serialized (`plan_point.preloads`)
  config.batch.define(:posts_comments) do |keys, context, plan_point|
    Comment.where(post_id: keys).where(is_spam: false).group_by(&:post_id)
  end
end

Defined Under Namespace

Modules: AttributeInstanceMethods, AttributeNormalizerInstanceMethods, CheckAttributeParamsInstanceMethods, ClassMethods, ConfigInstanceMethods, InstanceMethods, PlanPointInstanceMethods, PluginsExtensions, SeregaObjectSerializerInstanceMethods Classes: BatchConfig, CheckBatchOptKey, CheckBatchOptLoader, CheckOptBatch, SeregaBatchLoader, SeregaBatchLoaders

Class Method Summary collapse

Class Method Details

.after_load_plugin(serializer_class, **opts) ⇒ void

This method returns an undefined value.

Runs callbacks after plugin was attached

Parameters:

  • serializer_class (Class<Serega>)

    Current serializer class

  • opts (Hash)

    loaded plugins opts



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/serega/plugins/batch/batch.rb', line 112

def self.after_load_plugin(serializer_class, **opts)
  serializer_class::SeregaConfig.include(ConfigInstanceMethods)

  batch_loaders_class = Class.new(SeregaBatchLoaders)
  batch_loaders_class.serializer_class = serializer_class
  serializer_class.const_set(:SeregaBatchLoaders, batch_loaders_class)

  batch_loader_class = Class.new(SeregaBatchLoader)
  batch_loader_class.serializer_class = serializer_class
  serializer_class.const_set(:SeregaBatchLoader, batch_loader_class)

  if serializer_class.plugin_used?(:activerecord_preloads)
    require_relative "./lib/plugins_extensions/activerecord_preloads"
    serializer_class::SeregaBatchLoader.include(PluginsExtensions::ActiveRecordPreloads::BatchLoaderInstanceMethods)
  end

  if serializer_class.plugin_used?(:formatters)
    require_relative "./lib/plugins_extensions/formatters"
    serializer_class::SeregaBatchLoader.include(PluginsExtensions::Formatters::BatchLoaderInstanceMethods)
    serializer_class::SeregaAttribute.include(PluginsExtensions::Formatters::SeregaAttributeInstanceMethods)
  end

  if serializer_class.plugin_used?(:preloads)
    require_relative "./lib/plugins_extensions/preloads"
    serializer_class::SeregaAttributeNormalizer.include(PluginsExtensions::Preloads::AttributeNormalizerInstanceMethods)
  end

  config = serializer_class.config
  config.attribute_keys << :batch
  config.opts[:batch] = {loaders: {}, default_key: nil, auto_hide: false}
  config.batch.auto_hide = opts[:auto_hide] if opts.key?(:auto_hide)
  config.batch.default_key = opts[:default_key] if opts.key?(:default_key)
end

.load_plugin(serializer_class, **_opts) ⇒ void

This method returns an undefined value.

Applies plugin code to specific serializer

Parameters:

  • serializer_class (Class<Serega>)

    Current serializer class

  • _opts (Hash)

    Loaded plugins options



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/serega/plugins/batch/batch.rb', line 81

def self.load_plugin(serializer_class, **_opts)
  require_relative "./lib/batch_config"
  require_relative "./lib/loader"
  require_relative "./lib/loaders"
  require_relative "./lib/modules/attribute"
  require_relative "./lib/modules/attribute_normalizer"
  require_relative "./lib/modules/check_attribute_params"
  require_relative "./lib/modules/config"
  require_relative "./lib/modules/object_serializer"
  require_relative "./lib/modules/plan_point"
  require_relative "./lib/validations/check_batch_opt_key"
  require_relative "./lib/validations/check_batch_opt_loader"
  require_relative "./lib/validations/check_opt_batch"

  serializer_class.extend(ClassMethods)
  serializer_class.include(InstanceMethods)
  serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
  serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
  serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
  serializer_class::SeregaPlanPoint.include(PlanPointInstanceMethods)
  serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
end

.plugin_nameSymbol

Returns plugin name

Returns:

  • (Symbol)

    Plugin name



69
70
71
# File 'lib/serega/plugins/batch/batch.rb', line 69

def self.plugin_name
  :batch
end