module Serega::ClassMethods
Class methods of serializers: they define attributes and serialize
Attributes
Public Instance Methods
(Symbol | String name, **untyped opts) ?{ () [self: singleton(Serega)] → void } → SeregaAttribute
Source
# File lib/serega.rb, line 241 def attribute(name, **opts, &block) check_unlocked location = caller_locations.find { |caller_location| !caller_location.path.start_with?(LIB_PATH) } attribute = SeregaAttribute.new(self, name: name, opts: opts, block: block, location: location && "#{location.path}:#{location.lineno}") attributes[attribute.name] = attribute end
Adds an attribute. By default its value is object.<name>, and the options change that:
attribute :first_name attribute :name, method: :full_name attribute :email, hide: true attribute :posts, serializer: PostSerializer
A block defines the attributes of a nested serializer. It inherits from the :base_serializer option or config.base_serializer:
attribute :statistics, method: :itself do attribute :likes_count attribute :comments_count end
See Attributes for all options.
() → Hash[Symbol, SeregaAttribute]
Source
# File lib/serega.rb, line 160 def attributes @attributes end
Attributes by name, hidden and inherited ones too
UserSerializer.attributes.keys # => [:first_name, :email]
(Symbol | String name, untyped loader) → void
(Symbol | String name) { (untyped objects) → untyped } → void
(Symbol | String name) { (untyped objects, context context) → untyped } → void
(Symbol | String name) { (untyped objects, ctx: context) → untyped } → void
Source
# File lib/serega.rb, line 262 def batch(name, value = nil, &block) check_unlocked raise SeregaError, "Batch loader must be defined with a callable value or block" if !value == !block batch_loader = SeregaBatchLoader.new(name: name, block: value || block) batch_loaders[batch_loader.name] = batch_loader end
Defines a named batch loader: a callable or a block that receives the objects, and the context as a second parameter or as the :ctx keyword. It returns the values by object id. Subclasses inherit it.
batch :likes_count, ->(users) { Like.where(user: users).group(:user_id).count } batch(:rank) { |users, ctx:| Rank.for(users, ctx[:season]) } attribute :likes_count, batch: true
See Batch loading.
(untyped object, ?only: fields?, ?with: fields?, ?except: fields?, ?check_initiate_params: bool?, ?context: context?, ?many: bool?) → untyped
Source
# File lib/serega.rb, line 402 def call(object, only: nil, with: nil, except: nil, check_initiate_params: nil, context: nil, many: nil) # The serialization methods list each keyword instead of taking # `**opts`: a `**opts` Hash allocates on every call, even when empty. new(only: only, with: with, except: except, check_initiate_params: check_initiate_params) .to_h(object, context: context, many: many) end
Serializes an object or a list to a Hash or an Array of Hashes. nil serializes to nil.
-
only,except,with: fields to serialize, to skip and to add, see Selecting fields; -
check_initiate_params:falseskips unknown fields, by defaultconfig.check_initiate_params; -
context: data for attribute values and conditions; -
many:trueserializes a list,falseone object. By default anEnumerablethat is not aHashorStructis a list.
UserSerializer.to_h(user) # => {first_name: "Bruce"} UserSerializer.to_h([user], with: :email) # => [{first_name: "Bruce", email: "bruce@wayne.com"}] UserSerializer.to_h(user, context: {admin: true})
See Serializing.
(Symbol name, untyped formatter, ?allow_nil: bool) → void
(Symbol name, ?allow_nil: bool) { (untyped value) → untyped } → void
(Symbol name, ?allow_nil: bool) { (untyped value, context context) → untyped } → void
(Symbol name, ?allow_nil: bool) { (untyped value, ctx: context) → untyped } → void
Source
# File lib/serega.rb, line 287 def formatter(name, value = nil, allow_nil: false, &block) check_unlocked raise SeregaError, "Formatter name must be a Symbol" unless name.is_a?(Symbol) raise SeregaError, "Formatter must be defined with a value or a block" if !value == !block raise SeregaError, "Invalid option :allow_nil => #{allow_nil.inspect}. Must have a boolean value" unless allow_nil == true || allow_nil == false value ||= block SeregaValidations::CheckFormatter.call(name, value) formatters[name] = SeregaFormatters.build({use: value, allow_nil: allow_nil}) end
Defines a named formatter for the :format attribute option. A formatter is a method name called on the value, an Array of a method name and its arguments, or a callable or a block that receives the value, and the context as a second parameter or as the :ctx keyword. With allow_nil: true a nil value stays nil. Subclasses inherit it.
formatter :string, :to_s formatter :iso8601, [:iso8601, 3] formatter(:money) { |cents, ctx| "#{cents / 100.0} #{ctx[:currency]}" } attribute :created_at, format: :iso8601
See Formatters.
(Symbol name, **untyped opts) → Module
Source
# File lib/serega.rb, line 137 def plugin(name, **opts) check_unlocked raise SeregaError, "This plugin is already loaded" if plugin_used?(name) plugin = SeregaPlugins.find(name) plugin.apply(self, **opts) config.plugins << name plugin end
Turns on a built-in feature by name, with its options. Subclasses get it too.
plugin :root, root_one: :user, root_many: :users
() → untyped
(untyped handler) → untyped
() { (untyped objects, untyped preloads) → void } → untyped
Source
# File lib/serega.rb, line 338 def preload_with(value = nil, &block) return @preload_with if value.nil? && block.nil? check_unlocked handler = checked_handler(:preload_with, value, block) 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
Sets the handler that preloads the :preload value of an attribute. It runs once per attribute with a preload, with the objects to serialize and the preloads. Without arguments, returns the handler. Subclasses inherit it.
preload_with { |objects, preloads| RecordPreloader.call(objects, preloads) } preload_with AppPreloader
See Preloads.
() → untyped
(untyped handler) → untyped
() { (untyped objects) → untyped } → untyped
() { (untyped objects, context context) → untyped } → untyped
() { (untyped objects, ctx: context) → untyped } → untyped
Source
# File lib/serega.rb, line 364 def prepare_initial_objects(value = nil, &block) return @prepare_initial_objects if value.nil? && block.nil? check_unlocked handler = checked_handler(:prepare_initial_objects, value, block) signature = SeregaUtils::MethodSignature.call(handler, pos_limit: 2, keyword_args: [:ctx]) raise SeregaError, prepare_initial_objects_signature_error unless %w[1 2 1_ctx].include?(signature) @prepare_initial_objects_signature = signature @prepare_initial_objects = handler end
Sets the handler that replaces the objects given to the serializer, for example ids with records. It runs once per serialization, before Serega detects a list, and receives the objects, and the context as a second parameter or as the :ctx keyword. Objects of relations skip it. Without arguments, returns the handler.
prepare_initial_objects { |user_ids| User.where(id: user_ids) } prepare_initial_objects { |ids, ctx:| User.where(id: ids, account: ctx[:account]) } prepare_initial_objects UsersLoader
() → singleton(SeregaPresenter)?
() { () [self: singleton(SeregaPresenter)] → void } → singleton(SeregaPresenter)
Source
# File lib/serega.rb, line 315 def presenter(&block) return @presenter_class unless block check_unlocked @presenter_class ||= Class.new(SeregaPresenter) @presenter_class.class_exec(&block) presenter_blocks << block @presenter_class end
Defines presenter methods: attributes read their values from them. The block runs in the presenter class of the serializer, and each call adds methods. Returns the presenter class, nil without one.
attribute :name presenter do def name [first_name, last_name].compact.join(" ") end end
See Presenter.
(untyped object, ?only: fields?, ?with: fields?, ?except: fields?, ?check_initiate_params: bool?, ?context: context?, ?many: bool?) → untyped
Source
# File lib/serega.rb, line 419 def to_data(object, only: nil, with: nil, except: nil, check_initiate_params: nil, context: nil, many: nil) new(only: only, with: with, except: except, check_initiate_params: check_initiate_params) .to_data(object, context: context, many: many) end
Serializes like to_h, to Data objects
UserSerializer.to_data(user) # => #<data first_name="Bruce">
(untyped object, ?only: fields?, ?with: fields?, ?except: fields?, ?check_initiate_params: bool?, ?context: context?, ?many: bool?) → untyped
(untyped object, ?only: fields?, ?with: fields?, ?except: fields?, ?check_initiate_params: bool?, ?context: context?, ?many: bool?) → String
Source
# File lib/serega.rb, line 450 def to_json(object, only: nil, with: nil, except: nil, check_initiate_params: nil, context: nil, many: nil) new(only: only, with: with, except: except, check_initiate_params: check_initiate_params) .to_json(object, context: context, many: many) end
(untyped object, ?only: fields?, ?with: fields?, ?except: fields?, ?check_initiate_params: bool?, ?context: context?, ?many: bool?) → untyped
Source
# File lib/serega.rb, line 434 def to_struct(object, only: nil, with: nil, except: nil, check_initiate_params: nil, context: nil, many: nil) new(only: only, with: with, except: except, check_initiate_params: check_initiate_params) .to_struct(object, context: context, many: many) end
Serializes like to_h, to Struct objects
UserSerializer.to_struct(user) # => #<struct first_name="Bruce">