# frozen_string_literal: true module Upgrow # Base class for Repositories. It offers a basic API for the state all # Repositories should have, as well as the logic on how to materialize data # into Models. class BasicRepository class << self attr_writer :base attr_writer :model_class # model_class [Class] the Model class to be used to map and return the # materialized data as instances of the domain. Defaults to a constant # derived from the Repository class' name. For example, a `UserRepository` # will have its default Model class set to `User`. # # @return [Class] the Repository Model class. def model_class @model_class || default_model_class end # the base object to be used internally to retrieve the persisted data. # For example, a base class in which queries can be performed for a # relational database adapter. Defaults to `nil`. # # @return [Object] the Repository base. def base @base || default_base end private def default_base; end def default_model_class model_class_name = name.delete_suffix('Repository') Object.const_get(model_class_name) end end attr_reader :base, :model_class # Sets the Basic Repositorie's state. def initialize @base = self.class.base @model_class = self.class.model_class end # Represents the raw Hash of data attributes as a Model instance from the # Repositorie's Model class. # # @param model_class_or_attributes [Class, Hash<Symbol, Object>] the Model # class to be instantiated, in case it is a different class than the # Repositorie's Model class, or the list of attributes the model will # have, in case the Model class is the Repositorie's Model class. # @param attributes [Hash<Symbol, Object>] the list of attributes the Model # will have, in case the Model to be instantiated is passed as the first # argument. # # @return [Model] the Model instance populated with the given attributes. def to_model(model_class_or_attributes, attributes = {}) model_class = model_class_or_attributes if model_class_or_attributes.respond_to?(:transform_keys) model_class = self.model_class attributes = model_class_or_attributes end model_class.new(**attributes.transform_keys(&:to_sym)) end end end