Class: Api::V2::BaseResource Abstract

Inherits:
JSONAPI::Resource
  • Object
show all
Defined in:
app/resources/api/v2/base_resource.rb

Overview

This class is abstract.
Note:

This class is abstract and should not be instantiated directly.

Note:

For more information about JSON:API, see the JSON:API Specifications or refer to the JSONAPI::Resources package.

Provides a base class for JSON:API representations of ApplicationRecord sub-classes. This class extends JSONAPI::Resource and serves as the foundation for all API v2 resources.

Key Features:

  • Implements JSON:API standard resource handling.

  • Provides global model hints for common resource models.

  • Defines attribute and relationship access restrictions (readonly, write_once, writeonly).

  • Customizes the creatable, updatable, and fetchable fields logic.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.apply_includes(records, options = {}) ⇒ Object

Extends the default behaviour to add our default inclusions if provided



95
96
97
98
99
100
101
# File 'app/resources/api/v2/base_resource.rb', line 95

def self.apply_includes(records, options = {})
  if @default_includes.present?
    super(records.preload(*inclusions), options)
  else
    super
  end
end

.creatable_fields(context) ⇒ Set<Symbol>

Determines which fields can be set when creating a new resource.

Parameters:

  • context (Object)

    The request context, used to determine access permissions.

Returns:

  • (Set<Symbol>)

    A set of attributes and relationships that can be written when creating a resource.



58
59
60
61
# File 'app/resources/api/v2/base_resource.rb', line 58

def self.creatable_fields(context)
  super - _attributes.select { |_attr, options| options[:readonly] }.keys -
    _relationships.select { |_rel_key, rel| rel.options[:readonly] }.keys
end

.default_includes(*inclusions) ⇒ Object

Eager load specified models by default. Useful when attributes are dependent on an associated model.



86
87
88
# File 'app/resources/api/v2/base_resource.rb', line 86

def self.default_includes(*inclusions)
  @default_includes = inclusions.freeze
end

.inclusionsObject



90
91
92
# File 'app/resources/api/v2/base_resource.rb', line 90

def self.inclusions
  @default_includes || [].freeze
end

.resolve_relationship_names_to_relations(resource_klass, model_includes, options = {}) ⇒ Object

The majority of this is lifted from JSONAPI::Resource We've had to modify the when Symbol chunk to handle nested includes We disable the cops for the shared section to avoid accidental drift due to auto-correct. rubocop:disable all



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'app/resources/api/v2/base_resource.rb', line 108

def self.resolve_relationship_names_to_relations(resource_klass, model_includes, options = {})
  case model_includes
  when Array
    return model_includes.map { |value| resolve_relationship_names_to_relations(resource_klass, value, options) }
  when Hash
    model_includes.keys.each do |key|
      relationship = resource_klass._relationships[key]
      value = model_includes[key]
      model_includes.delete(key)

      # MODIFICATION BEGINS
      included_relationships =
        resolve_relationship_names_to_relations(relationship.resource_klass, value, options)
      model_includes[relationship.relation_name(options)] = relationship.resource_klass.inclusions +
        included_relationships
      # MODIFICATION ENDS
    end
    return model_includes
  when Symbol
    relationship = resource_klass._relationships[model_includes]

    # MODIFICATION BEGINS
    # return relationship.relation_name(options)
    inclusions = relationship.resource_klass.inclusions
    { relationship.relation_name(options) => inclusions }
    # MODIFICATION ENDS
  end
end

.updatable_fields(context) ⇒ Set<Symbol>

Determines which fields can be updated after a resource has been created.

Parameters:

  • context (Object)

    The request context, used to determine access permissions.

Returns:

  • (Set<Symbol>)

    A set of attributes and relationships that can be modified after creation.



67
68
69
70
# File 'app/resources/api/v2/base_resource.rb', line 67

def self.updatable_fields(context)
  super - _attributes.select { |_attr, options| options[:readonly] || options[:write_once] }.keys -
    _relationships.select { |_rel_key, rel| rel.options[:readonly] || rel.options[:write_once] }.keys
end

Instance Method Details

#fetchable_fieldsSet<Symbol>

Determines which fields can be read when fetching a resource.

Returns:

  • (Set<Symbol>)

    A set of attributes and relationships that can be retrieved.



79
80
81
82
# File 'app/resources/api/v2/base_resource.rb', line 79

def fetchable_fields
  super - self.class._attributes.select { |_attr, options| options[:writeonly] }.keys -
    self.class._relationships.select { |_rel_key, rel| rel.options[:writeonly] }.keys
end