Class: Kabk::RestEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/kabk/rest_engine.rb

Overview

Generic CRUD engine for any registered resource

Instance Method Summary collapse

Constructor Details

#initialize(resource_name) ⇒ RestEngine

Returns a new instance of RestEngine.

Parameters:

  • resource_name (String, Symbol)

Raises:



12
13
14
15
# File 'lib/kabk/rest_engine.rb', line 12

def initialize(resource_name)
  @resource = Registry.instance.get(resource_name)
  raise NotFoundError, "Resource not found" unless @resource
end

Instance Method Details

#create(params) ⇒ Hash

Create a new resource. Validates parameters against the schema, sanitizes inputs, and handles creation.

Parameters:

  • params (Hash)

    The raw input attributes from the request payload.

Returns:

  • (Hash)

    A standard protocol response hash with success, message, and data properties.

Raises:

  • (ApiError)

    If a unique constraint is violated.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/kabk/rest_engine.rb', line 76

def create(params)
  sanitized = Validator.validate_and_sanitize!(@resource, params)
  
  # Sequel model creation
  record = @resource.model_class.create(sanitized)
  
  hydrated_records = RelationHydrator.hydrate(@resource, [record])

  {
    success: true,
    message: "Operation completed successfully",
    data: hydrated_records.first
  }
rescue Sequel::UniqueConstraintViolation => e
  raise ApiError.new("Unique constraint violated", code: "CONFLICT", http_status: 409)
end

#delete(id) ⇒ Hash

Delete a resource by ID.

Parameters:

  • id (Integer, String)

    The primary key of the record.

Returns:

  • (Hash)

    A standard protocol response hash indicating success.

Raises:



133
134
135
136
137
138
139
140
141
142
143
# File 'lib/kabk/rest_engine.rb', line 133

def delete(id)
  record = @resource.model_class[id]
  raise NotFoundError, "Record not found" unless record

  record.destroy

  {
    success: true,
    message: "Record successfully deleted"
  }
end

#get(id) ⇒ Hash

Get single resource by ID and hydrate its relations.

Parameters:

  • id (Integer, String)

    The primary key of the record.

Returns:

  • (Hash)

    A standard protocol response hash with success and data properties.

Raises:



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/kabk/rest_engine.rb', line 59

def get(id)
  record = @resource.model_class[id]
  raise NotFoundError, "Record not found" unless record

  hydrated_records = RelationHydrator.hydrate(@resource, [record])
  
  {
    success: true,
    data: hydrated_records.first
  }
end

#list(params) ⇒ Hash

List resources with pagination, sorting, filtering, and relation hydration.

Parameters:

  • params (Hash)

    Request parameters (page, per_page, sort, filters).

Returns:

  • (Hash)

    A standard protocol response hash with success, data, and meta properties.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/kabk/rest_engine.rb', line 21

def list(params)
  dataset = QueryBuilder.build(@resource, params)
  
  # We check pagination extension methods
  if dataset.respond_to?(:pagination_record_count)
    total = dataset.pagination_record_count
    page = dataset.current_page
    per_page = dataset.page_size
    last_page = dataset.page_count
    records = dataset.all
  else
    # Fallback if pagination extension isn't loaded correctly
    records = dataset.all
    total = records.size
    page = 1
    per_page = total
    last_page = 1
  end

  hydrated_records = RelationHydrator.hydrate(@resource, records)

  {
    success: true,
    data: hydrated_records,
    meta: {
      total: total,
      page: page,
      per_page: per_page,
      last_page: last_page
    }
  }
end

#update(id, params) ⇒ Hash

Update an existing resource. Validates Optimistic Concurrency Control (OCC) if configured.

Parameters:

  • id (Integer, String)

    The primary key of the record.

  • params (Hash)

    The updated attributes from the request payload.

Returns:

  • (Hash)

    A standard protocol response hash with success, message, and data properties.

Raises:

  • (NotFoundError)

    If the record does not exist.

  • (ApiError)

    If OCC fails or a unique constraint is violated.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/kabk/rest_engine.rb', line 100

def update(id, params)
  record = @resource.model_class[id]
  raise NotFoundError, "Record not found" unless record

  # Validate OCC if applicable
  Concurrency.check!(@resource, record, params)

  sanitized = Validator.validate_and_sanitize!(@resource, params, is_update: true)
  
  # Update record
  # If concurrency_field is present, we omit it from standard updates as Sequel usually auto-manages timestamp or version
  # But wait, OCC in sequel can be done via plugin, or we just rely on standard update
  c_field = @resource.concurrency_field&.to_sym
  sanitized.delete(c_field) if c_field

  record.update(sanitized)
  
  hydrated_records = RelationHydrator.hydrate(@resource, [record])

  {
    success: true,
    message: "Operation completed successfully",
    data: hydrated_records.first
  }
rescue Sequel::UniqueConstraintViolation => e
  raise ApiError.new("Unique constraint violated", code: "CONFLICT", http_status: 409)
end