class ApiPresenter::Base

Attributes

current_user[R]
params[R]
relation[R]

Public Class Methods

call(**kwargs) click to toggle source

@example

@presenter = PostPresenter.call(
  current_user: current_user,
  relation:     relation,
  params:       params
)

@param (see initialize)

@return [ApiPresenter::Base]

# File lib/api_presenter/base.rb, line 17
def self.call(**kwargs)
  new(kwargs).call
end
new(current_user: nil, relation:, params: {}) click to toggle source

@param current_user [User] Optional. current_user context. @param relation [ActiveRecord::Relation, Array] Relation or array-wrapped record(s) to present @param params [Hash] Controller params @option params [Boolean] :count Optional. If true, return count only. @option params [String, Array] :include Optional. Associated resources to include. @option params [Boolean] :policies Optional. If true, resolve polciies for relation.

# File lib/api_presenter/base.rb, line 28
def initialize(current_user: nil, relation:, params: {})
  @current_user = current_user
  @relation     = relation
  @params       = params
end

Public Instance Methods

associations_map() click to toggle source

Hash map that defines the sources for included collection names

@example

def associations_map
  {
    categories:     { associations: { sub_category: :category } },
    sub_categories: { associations: :sub_category },
    users:          { associations: [:creator, :publisher] }
  }
end

@abstract

@return [Hash]

# File lib/api_presenter/base.rb, line 128
def associations_map
  {}
end
call() click to toggle source

@return [ApiPresenter::Base]

# File lib/api_presenter/base.rb, line 36
def call
  return self if count_only?
  initialize_resolvers
  call_resolvers
  self
end
collection() click to toggle source

Primary collection, empty if count requested

@return [ActiveRecord::Relation, Array<ActiveRecord::Base>]

# File lib/api_presenter/base.rb, line 47
def collection
  count_only? ? [] : relation
end
included_collection_names() click to toggle source

Class names of included collections

@example

[:categories, :sub_categories, :users]

@return [Array<Symbol>]

# File lib/api_presenter/base.rb, line 82
def included_collection_names
  @included_collection_names ||= Parsers::ParseIncludeParams.call(params[ApiPresenter.configuration.include_param])
end
included_collections() click to toggle source

Map of included collection names and loaded record

@example

{
  categories:     [#<Category id:1>],
  sub_categories: [#<SubCategory id:1>],
  users:          [#<User id:1>, #<User id:2]
}

@return [Hash]

# File lib/api_presenter/base.rb, line 97
def included_collections
  @included_collections_resolver ? @included_collections_resolver.resolved_collections : {}
end
policies() click to toggle source

Policies for the primary collection

@example

[
  { post_id: 1, update: true, destroy: true },
  { post_id: 2, update: false, destroy: false }
]

@return [<Array<Hash>]

# File lib/api_presenter/base.rb, line 71
def policies
  @policies_resolver ? @policies_resolver.resolved_policies : {}
end
policy_associations() click to toggle source

Policy associations to preload to optimize policy resolution

@example Single

def policy_associations
  :user_profile
end

@example Multiple

def policy_associations
  [:user_profile, :company]
end

@abstract

@return [Symbol, Array<Symbol>]

# File lib/api_presenter/base.rb, line 168
def policy_associations
  []
end
policy_methods() click to toggle source

Policy methods to resolve for the primary relation

@example Single

def policy_methods
  :update
end

@example Multiple

def policy_methods
  [:update, :destroy]
end

@abstract

@return [Symbol, Array<Symbol>]

# File lib/api_presenter/base.rb, line 148
def policy_methods
  []
end
preload(associations) click to toggle source

Preload additional records with the relation

@note Called by resolvers, but can also be called if additional data is required that does

not need to be loaded as an included collection, and for some reason cannot be chained
onto the original relation.

@param associations [Symbol, Array<Symbol>]

# File lib/api_presenter/base.rb, line 109
def preload(associations)
  @relation = @relation.preload(associations)
end
total_count() click to toggle source

Count of primary collection

@note Delegate to Kaminari's `total_count` property, or regular count if not a paginated relation

@return [Integer]

# File lib/api_presenter/base.rb, line 57
def total_count
  relation.respond_to?(:total_count) ? relation.total_count : relation.count
end

Private Instance Methods

call_resolvers() click to toggle source
# File lib/api_presenter/base.rb, line 191
def call_resolvers
  @policies_resolver.call if @policies_resolver
  @included_collections_resolver.call if @included_collections_resolver
end
count_only?() click to toggle source
# File lib/api_presenter/base.rb, line 174
def count_only?
  @count_only ||= !!params[ApiPresenter.configuration.count_param]
end
initialize_resolvers() click to toggle source
# File lib/api_presenter/base.rb, line 186
def initialize_resolvers
  @policies_resolver              = Resolvers::PoliciesResolver.new(self) if resolve_policies?
  @included_collections_resolver  = Resolvers::IncludedCollectionsResolver.new(self) if resolve_included_collctions?
end
resolve_included_collctions?() click to toggle source
# File lib/api_presenter/base.rb, line 182
def resolve_included_collctions?
  included_collection_names.any?
end
resolve_policies?() click to toggle source
# File lib/api_presenter/base.rb, line 178
def resolve_policies?
  @resolve_policies ||= current_user && !!params[ApiPresenter.configuration.policies_param]
end