class SBF::Client::DEFAULT_ENDPOINT

Attributes

base_uri[R]
orig_target_class[R]

Public Class Methods

new(target_class) click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 16
def initialize(target_class)
  @orig_target_class = target_class
end

Public Instance Methods

aggregate(filter = [], aggregate = {}) click to toggle source

Calls the aggregate route for the entity.

# File lib/stbaldricks/endpoints/lib/entity.rb, line 125
def aggregate(filter = [], aggregate = {})
  filter = filter.to_json unless filter.is_a? String
  aggregate = aggregate.to_json unless aggregate.is_a? String

  response = SBF::Client::Api::Request.get_request("#{base_uri}/aggregate", filter: filter, aggregate: aggregate)
  parsed_response_body = JSON.parse(response.body).symbolize!
  if ok?(response)
    data = parsed_response_body[:aggregate]
  else
    error = SBF::Client::ErrorEntity.new(parsed_response_body)
  end

  SBF::Client::Api::Response.new(http_code: response.code, data: data, error: error)
end
create(entity_or_hash, with = {}) click to toggle source

Calls the create route for the entity. Uses the class name to generate the uri @param with [Hash] The optional entity fields to include in the response @return entity [SBF::Client::BaseEntity]

# File lib/stbaldricks/endpoints/lib/entity.rb, line 36
def create(entity_or_hash, with = {})
  entity = entity_or_hash.is_a?(Hash) ? target_class.new(entity_or_hash) : entity_or_hash
  raise SBF::Client::Error, 'Invalid Entity' unless entity.is_a?(SBF::Client::BaseEntity)

  with = normalize_with(with, entity)
  create_data = entity.dirty_data
  create_data.store(:with, with)

  response = SBF::Client::Api::Request.post_request("#{base_uri}/create", create_data)

  hydrated_entity(response, create_data, entity)
end
delete(id) click to toggle source

Calls the delete route for the entity

# File lib/stbaldricks/endpoints/lib/entity.rb, line 141
def delete(id)
  response = SBF::Client::Api::Request.post_request("#{base_uri}/delete/#{id}")

  error = SBF::Client::ErrorEntity.new(JSON.parse(response.body).symbolize!) unless ok?(response)

  SBF::Client::Api::Response.new(http_code: response.code, data: nil, error: error)
end
find(filter = [], order = {}, limit = 20, offset = 0, with = {}) click to toggle source

Calls the find route for the entity.

# File lib/stbaldricks/endpoints/lib/entity.rb, line 92
def find(filter = [], order = {}, limit = 20, offset = 0, with = {})
  filter = filter.to_json unless filter.is_a? String
  order = order.to_json unless order.is_a? String
  with = normalize_with(with)

  response = SBF::Client::Api::Request.get_request("#{base_uri}/find", filter: filter, order: order, limit: limit, offset: offset, with: with)
  parsed_response_body = JSON.parse(response.body).symbolize!

  if ok?(response)
    parsed_response_body[:results].map! { |entity_data| target_class.new(entity_data, true) }
    SBF::Client::EntityCollection.new(parsed_response_body[:results], parsed_response_body[:total_count])
  else
    parsed_response_body = JSON.parse(response.body).symbolize!
    error = SBF::Client::ErrorEntity.new(parsed_response_body)
    SBF::Client::Api::Response.new(http_code: response.code, data: parsed_response_body[:data], error: error)
    collection = SBF::Client::EntityCollection.new
    collection.add_errors(error)
    collection.errors_http_code = response.code
    collection
  end
end
find_first(filter = [], order = {}, with = {}) click to toggle source

Calls the find route for the entity.

# File lib/stbaldricks/endpoints/lib/entity.rb, line 115
def find_first(filter = [], order = {}, with = {})
  response = find(filter, order, 1, 0, with)
  if response.is_a?(SBF::Client::EntityCollection)
    response.empty? ? nil : response.first
  else
    response
  end
end
get(id, with = {}) click to toggle source

Calls the get route for the entity. Uses the class name to generate the uri. @param id [integer] @return [SBF::Client::BaseEntity]

# File lib/stbaldricks/endpoints/lib/entity.rb, line 75
def get(id, with = {})
  with = normalize_with(with)

  response = SBF::Client::Api::Request.get_request("#{base_uri}/get/#{id}", with: with)

  if ok?(response)
    hydrated_entity(response, {}, nil)
  elsif response.code == 404
    nil
  else
    parsed_response_body = JSON.parse(response.body).symbolize!
    error = SBF::Client::ErrorEntity.new(parsed_response_body)
    SBF::Client::Api::Response.new(http_code: response.code, data: parsed_response_body[:data], error: error)
  end
end
save(entity_or_hash, with = {}) click to toggle source

Calls create if the id field is empty. Otherwise it calls update.

# File lib/stbaldricks/endpoints/lib/entity.rb, line 21
def save(entity_or_hash, with = {})
  if entity_or_hash.is_a?(SBF::Client::BaseEntity)
    return create(entity_or_hash, with) if !entity_or_hash.respond_to?(:id) || entity_or_hash.id.nil?

    update(entity_or_hash.id, entity_or_hash, with)
  else
    return create(entity_or_hash, with) if entity_or_hash[:id].nil?

    update(entity_or_hash[:id], entity_or_hash, with)
  end
end
update(id = nil, entity_or_hash = nil, with = {}) click to toggle source

Calls the update route for the entity. Uses the class name to generate the uri @param with [Hash] The optional entity fields to include in the response @return entity [SBF::Client::BaseEntity]

# File lib/stbaldricks/endpoints/lib/entity.rb, line 52
def update(id = nil, entity_or_hash = nil, with = {})
  if entity_or_hash.is_a?(SBF::Client::BaseEntity)
    # If someone has passed in an entity, just convert it to a hash
    data = entity_or_hash.dirty_data
  elsif entity_or_hash.is_a?(Hash)
    # If someone has passed in a hash, make sure all of it's values match fields in the entity class
    data = sanitize(entity_or_hash)
  else
    raise SBF::Client::Error, 'Invalid Data'
  end

  with = normalize_with(with, entity_or_hash)
  data.store(:with, with)

  uri = id ? "#{base_uri}/update/#{id}" : "#{base_uri}/update"
  response = SBF::Client::Api::Request.post_request(uri, data)

  hydrated_entity(response, data, entity_or_hash)
end

Private Instance Methods

hydrated_entity(response, data, entity_or_hash) click to toggle source

rubocop:disable Style/IdenticalConditionalBranches

# File lib/stbaldricks/endpoints/lib/entity.rb, line 234
def hydrated_entity(response, data, entity_or_hash)
  parsed_response_body = JSON.parse(response.body).symbolize!

  entity_or_hash.errors.clear if entity_or_hash.is_a?(SBF::Client::BaseEntity)

  if ok?(response)
    # Re-initialize the entity using the existing data as a base and overwriting with all data returned from the response
    # This will populate fields that have been auto-populated or defaulted on the db (e.g. id) into the original object

    new_data = parsed_response_body
    new_data = data.merge(parsed_response_body) if data.is_a?(Hash)

    if entity_or_hash.is_a?(SBF::Client::BaseEntity)
      entity_or_hash.send(:initialize_attributes, new_data)
      entity = entity_or_hash
    else
      entity = target_class.new(new_data)
    end

    # Reload entity and its sub-entities so that no fields have a 'changed' state
    entity.reload_recursive

    entity
  else
    error = SBF::Client::ApiErrorEntity.new(parsed_response_body.merge(http_code: response.code))
    entity = entity_or_hash.is_a?(SBF::Client::BaseEntity) ? entity_or_hash : target_class.new(entity_or_hash)
    entity.add_errors(error)
    entity.errors_http_code = response.code

    entity
  end
end
normalize_with(with, entity_or_hash = nil) click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 224
def normalize_with(with, entity_or_hash = nil)
  with ||= {}
  with = {}.tap { |hsh| with.each { |key| hsh[key] = nil } } if with.is_a? Array
  with = reconstitute_with(entity_or_hash).merge(with) if entity_or_hash.is_a? SBF::Client::BaseEntity
  with = with.to_json unless with.is_a? String
  with
end
ok?(response) click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 163
def ok?(response)
  response.code.to_s.start_with?('2')
end
reconstitute_with(entity) click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 201
def reconstitute_with(entity)
  return {} unless entity.class.respond_to?(:optional_attributes)

  {}.tap do |hsh|
    entity.class.optional_attributes.each do |attribute|
      next if entity.not_provided_attributes.include?(attribute)

      attribute_value = entity.send(attribute)

      if attribute_value.is_a?(Array)
        hsh[attribute] = attribute_value.inject({}) { |h, it| h.merge(reconstitute_with(it)) }
        next
      end

      next if attribute_value.class.demodulize.start_with?('Partial')
      next unless attribute_value.is_a? SBF::Client::BaseEntity

      hsh[attribute] = reconstitute_with(attribute_value)
    end
  end
end
sanitize(data, entity_class = nil) click to toggle source

Remove all data that doesn't map to an appropriate field for the object type

# File lib/stbaldricks/endpoints/lib/entity.rb, line 169
def sanitize(data, entity_class = nil)
  klass = entity_class || target_class

  return sanitize(data, klass) if klass.defined_attributes.empty?

  {}.tap do |hsh|
    data.each do |key, value|
      next unless klass.defined_attributes.include?(key)

      # We need to sanitize the sub objects if the value is a sub-entity
      if klass.entity_attributes.include?(key)
        value = sanitize_entity(key, value, klass)
      elsif klass.collection_attributes.include?(key)
        value = value.map { |value_item| sanitize_entity(key, value_item, klass) }
      end

      hsh[key] = value
    end
  end
end
sanitize_entity(key, value, klass = target_class) click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 191
def sanitize_entity(key, value, klass = target_class)
  entity_class_selector_method = :"select_#{key}_class"
  entity_class = klass.send(entity_class_selector_method, value)

  return nil if entity_class == NilClass

  entity_class.nil? ? value : sanitize(value, entity_class)
end
target_class() click to toggle source
# File lib/stbaldricks/endpoints/lib/entity.rb, line 149
def target_class
  class_name_pieces = @orig_target_class.to_s.split('::')
  full_name = (class_name_pieces[0..-2] + ['Full' + class_name_pieces.last]).join('::')
  Object.const_defined?(full_name) ? Object.const_get(full_name) : @orig_target_class
end