Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
elixir-pay-record / lib / elixir / pay / record / repository.rb
Size: Mime:
# frozen_string_literal: true

module Elixir
  module Pay
    module Record
      # Repository
      class Repository
        # include Aws::Record
        extend Dry::Configurable

        setting :indexs
        setting :entity
        setting :gsik
        setting :index_name
        setting :table_name
        setting :logger

        def initialize # rubocop:disable Metrics/CyclomaticComplexity
          raise ConfigTableName if self.class.config.table_name.nil?
          raise ConfigEntity if self.class.config.entity.nil?
          raise ConfigGsik if self.class.config.gsik.nil?
          raise IndexNotFound if self.class.config.index_name.nil?

          @kclass = Class.new do
            include(::Aws::Record)
            # set_table_name(repository.config.table_name)
            string_attr(:pk, hash_key: true)
            string_attr(:sk, range_key: true)
            string_attr(:gk)
            string_attr(:_v)
            map_attr(:_p)
          end

          @kclass.set_table_name self.class.config.table_name

          self.class.config.entity.schema.each do |key, value|
            kclass = process_attribute(value)

            case kclass
            when 'String' then
              @kclass.string_attr(key)
            when 'DateTime' then
              @kclass.datetime_attr(key)
            when 'Date' then
              @kclass.date_attr(key)
            when 'Float' then
              @kclass.float_attr(key)
            when 'Decimal' then
              @kclass.float_attr(key)
            when 'BigDecimal' then
              @kclass.float_attr(key)
            when 'Integer' then
              @kclass.float_attr(key)
            when 'Time' then
              @kclass.time_attr(key)
            when 'Array' then
              @kclass.list_attr(key)
            when 'Class' then
              @kclass.map_attr(key)
            when 'Hash' then
              @kclass.map_attr(key)
            end
          end
        end

        def create(entity)
          raise NotCreateEntity unless self.class.config.entity == entity.class

          class_name = entity.class.name.demodulize

          params = entity.to_h
                         .merge(pk: entity.id,
                                sk: class_name,
                                _v: self.class.config.gsik,
                                gk: entity.send(self.class.config.gsik))

          repo = @kclass.new

          repo.assign_attributes(params)

          repo.save!
        end

        def update(entity)
          raise NotCreateEntity unless self.class.config.entity == entity.class

          class_name = entity.class.name.demodulize

          params = entity.to_h
                         .merge(pk: entity.id,
                                sk: class_name,
                                _v: self.class.config.gsik,
                                gk: entity.send(self.class.config.gsik))

          repo = @kclass.new

          repo.assign_attributes(params)

          repo.save!
        end

        def find!(id)
          entity = find(id)

          raise NotFound if entity.nil?
        end

        def find(id)
          class_name = self.class.config.entity.name.demodulize

          opts = {
            key_condition_expression: '#pk = :pk and #sk = :sk',
            expression_attribute_names: {
              '#pk': 'pk',
              '#sk': 'sk'
            },
            expression_attribute_values: {
              ':pk': id,
              ':sk': class_name
            }
          }

          items = @kclass.query(opts).take(1)

          return nil if items.length.zero?

          convert(items[0])
        end

        def find_by(args)
          class_name = self.class.config.entity.name.demodulize

          opts = {
            index_name: self.class.config.index_name,
            key_condition_expression: '#sk = :sk',
            filter_expression: nil,
            expression_attribute_names: {
              '#sk': 'sk'
            },
            expression_attribute_values: {
              ':sk': class_name
            }
          }

          args.each_with_index do |item, index|
            key = item.first
            value = item.last

            if self.class.config.gsik == key.to_sym.to_s
              opts[:key_condition_expression] = "#{opts[:key_condition_expression]} and #gk = :gk"
              opts[:expression_attribute_values][':gk'] = value
            else
              opts[:filter_expression] = if opts[:filter_expression].nil?
                                           "#k#{index + 1} = :k#{index + 1}"
                                         else
                                           "#{opts[:filter_expression]} and #k#{index + 1} = :k#{index + 1}"
                                         end

              opts[:expression_attribute_names]["#k#{index + 1}"] = key
              opts[:expression_attribute_values][":k#{index + 1}"] = value
            end
          end

          items = @kclass.query(opts).take(1)

          return nil if items.length.zero?

          convert(items[0])
        end

        private

        def process_attribute(kclass)
          value = if kclass.class == Dry::Types::Sum
                    kclass.right.name
                  elsif kclass.class == Dry::Types::Sum::Constrained
                    kclass.right.name
                  elsif kclass.class == Dry::Types::Default
                    kclass.primitive.name
                  elsif kclass.class == Dry::Types::Constrained
                    kclass.primitive.name
                  elsif kclass.class == Dry::Types::Constructor
                    kclass.primitive.name
                  else
                    kclass.primitive.name
                  end
          value
        end

        def convert(item)
          entity = self.class.config.entity.new item.to_h

          entity
        end
      end
    end
  end
end