jpie 0.4.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.rubocop.yml +35 -110
- data/.travis.yml +7 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +312 -0
- data/README.md +2072 -140
- data/Rakefile +3 -14
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/jpie.gemspec +18 -35
- data/kiln/app/resources/user_message_resource.rb +2 -0
- data/lib/jpie.rb +3 -28
- data/lib/json_api/active_storage/deserialization.rb +106 -0
- data/lib/json_api/active_storage/detection.rb +74 -0
- data/lib/json_api/active_storage/serialization.rb +32 -0
- data/lib/json_api/configuration.rb +58 -0
- data/lib/json_api/controllers/base_controller.rb +26 -0
- data/lib/json_api/controllers/concerns/controller_helpers.rb +223 -0
- data/lib/json_api/controllers/concerns/resource_actions.rb +657 -0
- data/lib/json_api/controllers/relationships_controller.rb +504 -0
- data/lib/json_api/controllers/resources_controller.rb +6 -0
- data/lib/json_api/errors/parameter_not_allowed.rb +19 -0
- data/lib/json_api/railtie.rb +75 -0
- data/lib/json_api/resources/active_storage_blob_resource.rb +11 -0
- data/lib/json_api/resources/resource.rb +238 -0
- data/lib/json_api/resources/resource_loader.rb +35 -0
- data/lib/json_api/routing.rb +72 -0
- data/lib/json_api/serialization/deserializer.rb +362 -0
- data/lib/json_api/serialization/serializer.rb +320 -0
- data/lib/json_api/support/active_storage_support.rb +85 -0
- data/lib/json_api/support/collection_query.rb +406 -0
- data/lib/json_api/support/instrumentation.rb +42 -0
- data/lib/json_api/support/param_helpers.rb +51 -0
- data/lib/json_api/support/relationship_guard.rb +16 -0
- data/lib/json_api/support/relationship_helpers.rb +74 -0
- data/lib/json_api/support/resource_identifier.rb +87 -0
- data/lib/json_api/support/responders.rb +100 -0
- data/lib/json_api/support/response_helpers.rb +10 -0
- data/lib/json_api/support/sort_parsing.rb +21 -0
- data/lib/json_api/support/type_conversion.rb +21 -0
- data/lib/json_api/testing/test_helper.rb +76 -0
- data/lib/json_api/testing.rb +3 -0
- data/lib/{jpie → json_api}/version.rb +2 -2
- data/lib/json_api.rb +50 -0
- data/lib/rubocop/cop/custom/hash_value_omission.rb +53 -0
- metadata +50 -167
- data/.cursor/rules/dependencies.mdc +0 -19
- data/.cursor/rules/examples.mdc +0 -16
- data/.cursor/rules/git.mdc +0 -14
- data/.cursor/rules/project_structure.mdc +0 -30
- data/.cursor/rules/security.mdc +0 -14
- data/.cursor/rules/style.mdc +0 -15
- data/.cursor/rules/testing.mdc +0 -16
- data/.overcommit.yml +0 -35
- data/CHANGELOG.md +0 -164
- data/LICENSE.txt +0 -21
- data/examples/basic_example.md +0 -146
- data/examples/including_related_resources.md +0 -491
- data/examples/pagination.md +0 -303
- data/examples/relationships.md +0 -114
- data/examples/resource_attribute_configuration.md +0 -147
- data/examples/resource_meta_configuration.md +0 -244
- data/examples/single_table_inheritance.md +0 -160
- data/lib/jpie/configuration.rb +0 -12
- data/lib/jpie/controller/crud_actions.rb +0 -141
- data/lib/jpie/controller/error_handling/handler_setup.rb +0 -124
- data/lib/jpie/controller/error_handling/handlers.rb +0 -109
- data/lib/jpie/controller/error_handling.rb +0 -23
- data/lib/jpie/controller/json_api_validation.rb +0 -193
- data/lib/jpie/controller/parameter_parsing.rb +0 -78
- data/lib/jpie/controller/related_actions.rb +0 -45
- data/lib/jpie/controller/relationship_actions.rb +0 -291
- data/lib/jpie/controller/relationship_validation.rb +0 -117
- data/lib/jpie/controller/rendering.rb +0 -154
- data/lib/jpie/controller.rb +0 -45
- data/lib/jpie/deserializer.rb +0 -110
- data/lib/jpie/errors.rb +0 -117
- data/lib/jpie/generators/resource_generator.rb +0 -116
- data/lib/jpie/generators/templates/resource.rb.erb +0 -31
- data/lib/jpie/railtie.rb +0 -42
- data/lib/jpie/resource/attributable.rb +0 -112
- data/lib/jpie/resource/inferrable.rb +0 -43
- data/lib/jpie/resource/sortable.rb +0 -93
- data/lib/jpie/resource.rb +0 -147
- data/lib/jpie/routing.rb +0 -59
- data/lib/jpie/rspec.rb +0 -71
- data/lib/jpie/serializer.rb +0 -205
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# Meta Field Configuration Example
|
|
2
|
-
|
|
3
|
-
This example demonstrates all the different ways to define and configure meta fields in JPie, focusing on the various configuration patterns and syntax options available.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
### 1. Article model
|
|
8
|
-
```ruby
|
|
9
|
-
class Article < ActiveRecord::Base
|
|
10
|
-
validates :title, presence: true
|
|
11
|
-
validates :content, presence: true
|
|
12
|
-
validates :status, inclusion: { in: %w[draft published archived] }
|
|
13
|
-
|
|
14
|
-
belongs_to :author, class_name: 'User'
|
|
15
|
-
|
|
16
|
-
def word_count
|
|
17
|
-
content.split.length
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def reading_time_minutes
|
|
21
|
-
(word_count / 200.0).ceil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### 2. Resource with All Meta Field Configuration Types
|
|
27
|
-
```ruby
|
|
28
|
-
class ArticleResource < JPie::Resource
|
|
29
|
-
# 1. Basic meta attributes - direct model access and custom methods
|
|
30
|
-
meta_attributes :created_at, :updated_at
|
|
31
|
-
meta_attribute :reading_time
|
|
32
|
-
|
|
33
|
-
# 2. Meta attribute with attr mapping (maps to different model attribute)
|
|
34
|
-
meta_attribute :author_name, attr: :author_email
|
|
35
|
-
|
|
36
|
-
# 3. Meta attribute with block (legacy style)
|
|
37
|
-
meta_attribute :word_count do
|
|
38
|
-
object.word_count
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# 4. Meta attribute with proc block (alternative legacy style)
|
|
42
|
-
meta_attribute :character_count, block: proc { object.content.length }
|
|
43
|
-
|
|
44
|
-
# 5. Short alias syntax (modern style)
|
|
45
|
-
meta :api_version
|
|
46
|
-
metas :request_id, :cache_key
|
|
47
|
-
|
|
48
|
-
# 6. Custom meta method for dynamic metadata
|
|
49
|
-
def meta
|
|
50
|
-
# Start with declared meta attributes
|
|
51
|
-
base_meta = super
|
|
52
|
-
|
|
53
|
-
# Add dynamic metadata
|
|
54
|
-
dynamic_meta = {
|
|
55
|
-
timestamp: Time.current.iso8601,
|
|
56
|
-
resource_version: '2.1'
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# Conditional metadata based on context
|
|
60
|
-
if context[:include_debug]
|
|
61
|
-
dynamic_meta[:debug_info] = {
|
|
62
|
-
object_class: object.class.name,
|
|
63
|
-
context_keys: context.keys
|
|
64
|
-
}
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Merge and return
|
|
68
|
-
base_meta.merge(dynamic_meta)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
private
|
|
72
|
-
|
|
73
|
-
# Custom method for reading_time meta attribute
|
|
74
|
-
def reading_time
|
|
75
|
-
{
|
|
76
|
-
minutes: object.reading_time_minutes,
|
|
77
|
-
formatted: "#{object.reading_time_minutes} min read"
|
|
78
|
-
}
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Meta attribute accessing context
|
|
82
|
-
def user_role
|
|
83
|
-
context[:current_user]&.role || 'anonymous'
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Meta attribute with conditional logic
|
|
87
|
-
def edit_permissions
|
|
88
|
-
current_user = context[:current_user]
|
|
89
|
-
return false unless current_user
|
|
90
|
-
|
|
91
|
-
current_user.admin? || current_user == object.author
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Meta attributes using short alias syntax
|
|
95
|
-
def api_version
|
|
96
|
-
'1.0'
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def request_id
|
|
100
|
-
context[:request_id] || SecureRandom.uuid
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def cache_key
|
|
104
|
-
"article:#{object.id}:#{object.updated_at.to_i}"
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## HTTP Examples
|
|
110
|
-
|
|
111
|
-
### Create Article
|
|
112
|
-
```http
|
|
113
|
-
POST /articles
|
|
114
|
-
Content-Type: application/vnd.api+json
|
|
115
|
-
Authorization: Bearer user_token
|
|
116
|
-
|
|
117
|
-
{
|
|
118
|
-
"data": {
|
|
119
|
-
"type": "articles",
|
|
120
|
-
"attributes": {
|
|
121
|
-
"title": "Meta Field Configuration Guide",
|
|
122
|
-
"content": "This guide demonstrates all the different ways to configure meta fields in JPie...",
|
|
123
|
-
"status": "draft"
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
HTTP/1.1 201 Created
|
|
129
|
-
Content-Type: application/vnd.api+json
|
|
130
|
-
|
|
131
|
-
{
|
|
132
|
-
"data": {
|
|
133
|
-
"id": "1",
|
|
134
|
-
"type": "articles",
|
|
135
|
-
"attributes": {
|
|
136
|
-
"title": "Meta Field Configuration Guide",
|
|
137
|
-
"content": "This guide demonstrates all the different ways to configure meta fields in JPie...",
|
|
138
|
-
"status": "draft"
|
|
139
|
-
},
|
|
140
|
-
"meta": {
|
|
141
|
-
"created_at": "2024-01-15T10:30:00Z",
|
|
142
|
-
"updated_at": "2024-01-15T10:30:00Z",
|
|
143
|
-
"reading_time": {
|
|
144
|
-
"minutes": 3,
|
|
145
|
-
"formatted": "3 min read"
|
|
146
|
-
},
|
|
147
|
-
"author_name": "john@example.com",
|
|
148
|
-
"word_count": 450,
|
|
149
|
-
"character_count": 2700,
|
|
150
|
-
"api_version": "1.0",
|
|
151
|
-
"request_id": "req_abc123def456",
|
|
152
|
-
"cache_key": "article:1:1705492800",
|
|
153
|
-
"timestamp": "2024-03-15T16:45:30Z",
|
|
154
|
-
"resource_version": "2.1"
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Update Article
|
|
161
|
-
```http
|
|
162
|
-
PATCH /articles/1
|
|
163
|
-
Content-Type: application/vnd.api+json
|
|
164
|
-
Authorization: Bearer user_token
|
|
165
|
-
|
|
166
|
-
{
|
|
167
|
-
"data": {
|
|
168
|
-
"id": "1",
|
|
169
|
-
"type": "articles",
|
|
170
|
-
"attributes": {
|
|
171
|
-
"status": "published"
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
HTTP/1.1 200 OK
|
|
177
|
-
Content-Type: application/vnd.api+json
|
|
178
|
-
|
|
179
|
-
{
|
|
180
|
-
"data": {
|
|
181
|
-
"id": "1",
|
|
182
|
-
"type": "articles",
|
|
183
|
-
"attributes": {
|
|
184
|
-
"title": "Meta Field Configuration Guide",
|
|
185
|
-
"content": "This guide demonstrates all the different ways to configure meta fields in JPie...",
|
|
186
|
-
"status": "published"
|
|
187
|
-
},
|
|
188
|
-
"meta": {
|
|
189
|
-
"created_at": "2024-01-15T10:30:00Z",
|
|
190
|
-
"updated_at": "2024-01-16T14:20:00Z",
|
|
191
|
-
"reading_time": {
|
|
192
|
-
"minutes": 3,
|
|
193
|
-
"formatted": "3 min read"
|
|
194
|
-
},
|
|
195
|
-
"author_name": "john@example.com",
|
|
196
|
-
"word_count": 450,
|
|
197
|
-
"character_count": 2700,
|
|
198
|
-
"api_version": "1.0",
|
|
199
|
-
"request_id": "req_xyz789ghi012",
|
|
200
|
-
"cache_key": "article:1:1705492800",
|
|
201
|
-
"timestamp": "2024-03-16T14:20:00Z",
|
|
202
|
-
"resource_version": "2.1"
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Get Article with All Meta Field Configurations
|
|
209
|
-
```http
|
|
210
|
-
GET /articles/1
|
|
211
|
-
Accept: application/vnd.api+json
|
|
212
|
-
Authorization: Bearer user_token
|
|
213
|
-
|
|
214
|
-
HTTP/1.1 200 OK
|
|
215
|
-
Content-Type: application/vnd.api+json
|
|
216
|
-
|
|
217
|
-
{
|
|
218
|
-
"data": {
|
|
219
|
-
"id": "1",
|
|
220
|
-
"type": "articles",
|
|
221
|
-
"attributes": {
|
|
222
|
-
"title": "Meta Field Configuration Guide",
|
|
223
|
-
"content": "This guide demonstrates all the different ways to configure meta fields in JPie...",
|
|
224
|
-
"status": "published"
|
|
225
|
-
},
|
|
226
|
-
"meta": {
|
|
227
|
-
"created_at": "2024-01-15T10:30:00Z",
|
|
228
|
-
"updated_at": "2024-01-16T14:20:00Z",
|
|
229
|
-
"reading_time": {
|
|
230
|
-
"minutes": 3,
|
|
231
|
-
"formatted": "3 min read"
|
|
232
|
-
},
|
|
233
|
-
"author_name": "john@example.com",
|
|
234
|
-
"word_count": 450,
|
|
235
|
-
"character_count": 2700,
|
|
236
|
-
"api_version": "1.0",
|
|
237
|
-
"request_id": "req_abc123def456",
|
|
238
|
-
"cache_key": "article:1:1705492800",
|
|
239
|
-
"timestamp": "2024-03-16T14:20:00Z",
|
|
240
|
-
"resource_version": "2.1"
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
```
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# Single Table Inheritance (STI) Example
|
|
2
|
-
|
|
3
|
-
This example demonstrates the minimal setup required to implement Single Table Inheritance with JPie resources and controllers.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
### 1. Base Model (`app/models/vehicle.rb`)
|
|
8
|
-
```ruby
|
|
9
|
-
class Vehicle < ApplicationRecord
|
|
10
|
-
validates :name, presence: true
|
|
11
|
-
validates :brand, presence: true
|
|
12
|
-
validates :year, presence: true
|
|
13
|
-
end
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### 2. STI Models (`app/models/car.rb`, `app/models/truck.rb`)
|
|
17
|
-
```ruby
|
|
18
|
-
class Car < Vehicle
|
|
19
|
-
validates :engine_size, presence: true
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class Truck < Vehicle
|
|
23
|
-
validates :cargo_capacity, presence: true
|
|
24
|
-
end
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### 3. Base Resource (`app/resources/vehicle_resource.rb`)
|
|
28
|
-
```ruby
|
|
29
|
-
class VehicleResource < JPie::Resource
|
|
30
|
-
attributes :name, :brand, :year
|
|
31
|
-
end
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### 4. STI Resources (`app/resources/car_resource.rb`, `app/resources/truck_resource.rb`)
|
|
35
|
-
```ruby
|
|
36
|
-
class CarResource < VehicleResource
|
|
37
|
-
attributes :engine_size
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
class TruckResource < VehicleResource
|
|
41
|
-
attributes :cargo_capacity
|
|
42
|
-
end
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### 5. Controller (`app/controllers/vehicles_controller.rb`)
|
|
46
|
-
```ruby
|
|
47
|
-
class VehiclesController < ApplicationController
|
|
48
|
-
include JPie::Controller
|
|
49
|
-
end
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### 6. Routes (`config/routes.rb`)
|
|
53
|
-
```ruby
|
|
54
|
-
Rails.application.routes.draw do
|
|
55
|
-
resources :vehicles
|
|
56
|
-
end
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## HTTP Examples
|
|
60
|
-
|
|
61
|
-
### Create Car
|
|
62
|
-
```http
|
|
63
|
-
POST /vehicles
|
|
64
|
-
Content-Type: application/vnd.api+json
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
"data": {
|
|
68
|
-
"type": "cars",
|
|
69
|
-
"attributes": {
|
|
70
|
-
"name": "Civic",
|
|
71
|
-
"brand": "Honda",
|
|
72
|
-
"year": 2024,
|
|
73
|
-
"engine_size": 1500
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
HTTP/1.1 201 Created
|
|
79
|
-
Content-Type: application/vnd.api+json
|
|
80
|
-
|
|
81
|
-
{
|
|
82
|
-
"data": {
|
|
83
|
-
"id": "1",
|
|
84
|
-
"type": "cars",
|
|
85
|
-
"attributes": {
|
|
86
|
-
"name": "Civic",
|
|
87
|
-
"brand": "Honda",
|
|
88
|
-
"year": 2024,
|
|
89
|
-
"engine_size": 1500
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Update Car
|
|
96
|
-
```http
|
|
97
|
-
PATCH /vehicles/1
|
|
98
|
-
Content-Type: application/vnd.api+json
|
|
99
|
-
|
|
100
|
-
{
|
|
101
|
-
"data": {
|
|
102
|
-
"id": "1",
|
|
103
|
-
"type": "cars",
|
|
104
|
-
"attributes": {
|
|
105
|
-
"name": "Civic Hybrid",
|
|
106
|
-
"engine_size": 1800
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
HTTP/1.1 200 OK
|
|
112
|
-
Content-Type: application/vnd.api+json
|
|
113
|
-
|
|
114
|
-
{
|
|
115
|
-
"data": {
|
|
116
|
-
"id": "1",
|
|
117
|
-
"type": "cars",
|
|
118
|
-
"attributes": {
|
|
119
|
-
"name": "Civic Hybrid",
|
|
120
|
-
"brand": "Honda",
|
|
121
|
-
"year": 2024,
|
|
122
|
-
"engine_size": 1800
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Get Mixed Vehicles
|
|
129
|
-
```http
|
|
130
|
-
GET /vehicles
|
|
131
|
-
Accept: application/vnd.api+json
|
|
132
|
-
|
|
133
|
-
HTTP/1.1 200 OK
|
|
134
|
-
Content-Type: application/vnd.api+json
|
|
135
|
-
|
|
136
|
-
{
|
|
137
|
-
"data": [
|
|
138
|
-
{
|
|
139
|
-
"id": "1",
|
|
140
|
-
"type": "cars",
|
|
141
|
-
"attributes": {
|
|
142
|
-
"name": "Civic",
|
|
143
|
-
"brand": "Honda",
|
|
144
|
-
"year": 2024,
|
|
145
|
-
"engine_size": 1500
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
"id": "2",
|
|
150
|
-
"type": "trucks",
|
|
151
|
-
"attributes": {
|
|
152
|
-
"name": "F-150",
|
|
153
|
-
"brand": "Ford",
|
|
154
|
-
"year": 2024,
|
|
155
|
-
"cargo_capacity": 1000
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
]
|
|
159
|
-
}
|
|
160
|
-
```
|
data/lib/jpie/configuration.rb
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module JPie
|
|
4
|
-
module Controller
|
|
5
|
-
module CrudActions
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
|
|
8
|
-
class_methods do
|
|
9
|
-
def jsonapi_resource(resource_class)
|
|
10
|
-
setup_jsonapi_resource(resource_class)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# More concise alias for modern Rails style
|
|
14
|
-
alias_method :resource, :jsonapi_resource
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
def setup_jsonapi_resource(resource_class)
|
|
19
|
-
define_method :resource_class do
|
|
20
|
-
resource_class
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Define automatic CRUD methods
|
|
24
|
-
define_automatic_crud_methods(resource_class)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def define_automatic_crud_methods(resource_class)
|
|
28
|
-
define_index_method(resource_class)
|
|
29
|
-
define_show_method(resource_class)
|
|
30
|
-
define_create_method(resource_class)
|
|
31
|
-
define_update_method(resource_class)
|
|
32
|
-
define_destroy_method(resource_class)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def define_index_method(resource_class)
|
|
36
|
-
define_method :index do
|
|
37
|
-
validate_include_params
|
|
38
|
-
validate_sort_params
|
|
39
|
-
resources = resource_class.scope(context)
|
|
40
|
-
sort_fields = parse_sort_params
|
|
41
|
-
resources = resource_class.sort(resources, sort_fields) if sort_fields.any?
|
|
42
|
-
|
|
43
|
-
pagination_params = parse_pagination_params
|
|
44
|
-
original_resources = resources
|
|
45
|
-
resources = apply_pagination(resources, pagination_params)
|
|
46
|
-
|
|
47
|
-
render_jsonapi(resources, pagination: pagination_params, original_scope: original_resources)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def define_show_method(resource_class)
|
|
52
|
-
define_method :show do
|
|
53
|
-
validate_include_params
|
|
54
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
55
|
-
render_jsonapi(resource)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def define_create_method(resource_class)
|
|
60
|
-
define_method :create do
|
|
61
|
-
validate_json_api_request
|
|
62
|
-
attributes = deserialize_params
|
|
63
|
-
resource = resource_class.model.create!(attributes)
|
|
64
|
-
render_jsonapi(resource, status: :created)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def define_update_method(resource_class)
|
|
69
|
-
define_method :update do
|
|
70
|
-
validate_json_api_request
|
|
71
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
72
|
-
attributes = deserialize_params
|
|
73
|
-
resource.update!(attributes)
|
|
74
|
-
render_jsonapi(resource)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def define_destroy_method(resource_class)
|
|
79
|
-
define_method :destroy do
|
|
80
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
81
|
-
resource.destroy!
|
|
82
|
-
head :no_content
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# These methods can still be called manually or used to override defaults
|
|
88
|
-
def index
|
|
89
|
-
validate_include_params
|
|
90
|
-
validate_sort_params
|
|
91
|
-
resources = resource_class.scope(context)
|
|
92
|
-
sort_fields = parse_sort_params
|
|
93
|
-
resources = resource_class.sort(resources, sort_fields) if sort_fields.any?
|
|
94
|
-
|
|
95
|
-
pagination_params = parse_pagination_params
|
|
96
|
-
original_resources = resources
|
|
97
|
-
resources = apply_pagination(resources, pagination_params)
|
|
98
|
-
|
|
99
|
-
render_jsonapi(resources, pagination: pagination_params, original_scope: original_resources)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def show
|
|
103
|
-
validate_include_params
|
|
104
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
105
|
-
render_jsonapi(resource)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def create
|
|
109
|
-
validate_json_api_request
|
|
110
|
-
attributes = deserialize_params
|
|
111
|
-
resource = model_class.create!(attributes)
|
|
112
|
-
render_jsonapi(resource, status: :created)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def update
|
|
116
|
-
validate_json_api_request
|
|
117
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
118
|
-
attributes = deserialize_params
|
|
119
|
-
resource.update!(attributes)
|
|
120
|
-
render_jsonapi(resource)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def destroy
|
|
124
|
-
resource = resource_class.scope(context).find(params[:id])
|
|
125
|
-
resource.destroy!
|
|
126
|
-
head :no_content
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
private
|
|
130
|
-
|
|
131
|
-
def apply_pagination(resources, pagination_params)
|
|
132
|
-
return resources unless pagination_params[:per_page]
|
|
133
|
-
|
|
134
|
-
page = pagination_params[:page] || 1
|
|
135
|
-
per_page = pagination_params[:per_page]
|
|
136
|
-
|
|
137
|
-
resources.limit(per_page).offset((page - 1) * per_page)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module JPie
|
|
4
|
-
module Controller
|
|
5
|
-
module ErrorHandling
|
|
6
|
-
module HandlerSetup
|
|
7
|
-
extend ActiveSupport::Concern
|
|
8
|
-
|
|
9
|
-
class_methods do
|
|
10
|
-
# Allow applications to easily disable all JPie error handlers
|
|
11
|
-
def disable_jpie_error_handlers
|
|
12
|
-
self.jpie_error_handlers_enabled = false
|
|
13
|
-
# Remove any already-added handlers
|
|
14
|
-
remove_jpie_handlers
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Allow applications to enable specific handlers
|
|
18
|
-
def enable_jpie_error_handler(error_class, method_name = nil)
|
|
19
|
-
method_name ||= :"handle_#{error_class.name.demodulize.underscore}"
|
|
20
|
-
rescue_from error_class, with: method_name
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Check for application-defined error handlers
|
|
24
|
-
def rescue_handler?(exception_class)
|
|
25
|
-
# Use Rails' rescue_handlers method to check for existing handlers
|
|
26
|
-
return false unless respond_to?(:rescue_handlers, true)
|
|
27
|
-
|
|
28
|
-
begin
|
|
29
|
-
rescue_handlers.any? { |handler| handler.first == exception_class.name }
|
|
30
|
-
rescue NoMethodError
|
|
31
|
-
false
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def setup_jpie_error_handlers
|
|
38
|
-
setup_jpie_specific_handlers
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def setup_jpie_specific_handlers
|
|
42
|
-
setup_core_error_handlers
|
|
43
|
-
setup_activerecord_handlers
|
|
44
|
-
setup_json_api_compliance_handlers
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def setup_core_error_handlers
|
|
48
|
-
return if rescue_handler?(JPie::Errors::Error)
|
|
49
|
-
|
|
50
|
-
rescue_from JPie::Errors::Error, with: :handle_jpie_error
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def setup_activerecord_handlers
|
|
54
|
-
setup_not_found_handler
|
|
55
|
-
setup_invalid_record_handler
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def setup_not_found_handler
|
|
59
|
-
return if rescue_handler?(ActiveRecord::RecordNotFound)
|
|
60
|
-
|
|
61
|
-
rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def setup_invalid_record_handler
|
|
65
|
-
return if rescue_handler?(ActiveRecord::RecordInvalid)
|
|
66
|
-
|
|
67
|
-
rescue_from ActiveRecord::RecordInvalid, with: :handle_record_invalid
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def setup_json_api_compliance_handlers
|
|
71
|
-
setup_json_api_request_handler
|
|
72
|
-
setup_include_handlers
|
|
73
|
-
setup_sort_handlers
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def setup_json_api_request_handler
|
|
77
|
-
return if rescue_handler?(JPie::Errors::InvalidJsonApiRequestError)
|
|
78
|
-
|
|
79
|
-
rescue_from JPie::Errors::InvalidJsonApiRequestError, with: :handle_invalid_json_api_request
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def setup_include_handlers
|
|
83
|
-
setup_unsupported_include_handler
|
|
84
|
-
setup_invalid_include_handler
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def setup_unsupported_include_handler
|
|
88
|
-
return if rescue_handler?(JPie::Errors::UnsupportedIncludeError)
|
|
89
|
-
|
|
90
|
-
rescue_from JPie::Errors::UnsupportedIncludeError, with: :handle_unsupported_include
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def setup_invalid_include_handler
|
|
94
|
-
return if rescue_handler?(JPie::Errors::InvalidIncludeParameterError)
|
|
95
|
-
|
|
96
|
-
rescue_from JPie::Errors::InvalidIncludeParameterError, with: :handle_invalid_include_parameter
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def setup_sort_handlers
|
|
100
|
-
setup_unsupported_sort_handler
|
|
101
|
-
setup_invalid_sort_handler
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def setup_unsupported_sort_handler
|
|
105
|
-
return if rescue_handler?(JPie::Errors::UnsupportedSortFieldError)
|
|
106
|
-
|
|
107
|
-
rescue_from JPie::Errors::UnsupportedSortFieldError, with: :handle_unsupported_sort_field
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def setup_invalid_sort_handler
|
|
111
|
-
return if rescue_handler?(JPie::Errors::InvalidSortParameterError)
|
|
112
|
-
|
|
113
|
-
rescue_from JPie::Errors::InvalidSortParameterError, with: :handle_invalid_sort_parameter
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def remove_jpie_handlers
|
|
117
|
-
# This is a placeholder - Rails doesn't provide an easy way to remove specific handlers
|
|
118
|
-
# In practice, applications should use the disable_jpie_error_handlers before including
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
end
|