jpie 0.4.5 → 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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +35 -110
  5. data/.travis.yml +7 -0
  6. data/Gemfile +21 -0
  7. data/Gemfile.lock +312 -0
  8. data/README.md +2072 -140
  9. data/Rakefile +3 -14
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/jpie.gemspec +18 -35
  13. data/kiln/app/resources/user_message_resource.rb +2 -0
  14. data/lib/jpie.rb +3 -24
  15. data/lib/json_api/active_storage/deserialization.rb +106 -0
  16. data/lib/json_api/active_storage/detection.rb +74 -0
  17. data/lib/json_api/active_storage/serialization.rb +32 -0
  18. data/lib/json_api/configuration.rb +58 -0
  19. data/lib/json_api/controllers/base_controller.rb +26 -0
  20. data/lib/json_api/controllers/concerns/controller_helpers.rb +223 -0
  21. data/lib/json_api/controllers/concerns/resource_actions.rb +657 -0
  22. data/lib/json_api/controllers/relationships_controller.rb +504 -0
  23. data/lib/json_api/controllers/resources_controller.rb +6 -0
  24. data/lib/json_api/errors/parameter_not_allowed.rb +19 -0
  25. data/lib/json_api/railtie.rb +75 -0
  26. data/lib/json_api/resources/active_storage_blob_resource.rb +11 -0
  27. data/lib/json_api/resources/resource.rb +238 -0
  28. data/lib/json_api/resources/resource_loader.rb +35 -0
  29. data/lib/json_api/routing.rb +72 -0
  30. data/lib/json_api/serialization/deserializer.rb +362 -0
  31. data/lib/json_api/serialization/serializer.rb +320 -0
  32. data/lib/json_api/support/active_storage_support.rb +85 -0
  33. data/lib/json_api/support/collection_query.rb +406 -0
  34. data/lib/json_api/support/instrumentation.rb +42 -0
  35. data/lib/json_api/support/param_helpers.rb +51 -0
  36. data/lib/json_api/support/relationship_guard.rb +16 -0
  37. data/lib/json_api/support/relationship_helpers.rb +74 -0
  38. data/lib/json_api/support/resource_identifier.rb +87 -0
  39. data/lib/json_api/support/responders.rb +100 -0
  40. data/lib/json_api/support/response_helpers.rb +10 -0
  41. data/lib/json_api/support/sort_parsing.rb +21 -0
  42. data/lib/json_api/support/type_conversion.rb +21 -0
  43. data/lib/json_api/testing/test_helper.rb +76 -0
  44. data/lib/json_api/testing.rb +3 -0
  45. data/lib/{jpie → json_api}/version.rb +2 -2
  46. data/lib/json_api.rb +50 -0
  47. data/lib/rubocop/cop/custom/hash_value_omission.rb +53 -0
  48. metadata +50 -169
  49. data/.cursor/rules/dependencies.mdc +0 -19
  50. data/.cursor/rules/examples.mdc +0 -16
  51. data/.cursor/rules/git.mdc +0 -14
  52. data/.cursor/rules/project_structure.mdc +0 -30
  53. data/.cursor/rules/publish_gem.mdc +0 -73
  54. data/.cursor/rules/security.mdc +0 -14
  55. data/.cursor/rules/style.mdc +0 -15
  56. data/.cursor/rules/testing.mdc +0 -16
  57. data/.overcommit.yml +0 -35
  58. data/CHANGELOG.md +0 -164
  59. data/LICENSE.txt +0 -21
  60. data/PUBLISHING.md +0 -111
  61. data/examples/basic_example.md +0 -146
  62. data/examples/including_related_resources.md +0 -491
  63. data/examples/pagination.md +0 -303
  64. data/examples/relationships.md +0 -114
  65. data/examples/resource_attribute_configuration.md +0 -147
  66. data/examples/resource_meta_configuration.md +0 -244
  67. data/examples/rspec_testing.md +0 -130
  68. data/examples/single_table_inheritance.md +0 -160
  69. data/lib/jpie/configuration.rb +0 -12
  70. data/lib/jpie/controller/crud_actions.rb +0 -141
  71. data/lib/jpie/controller/error_handling/handler_setup.rb +0 -124
  72. data/lib/jpie/controller/error_handling/handlers.rb +0 -109
  73. data/lib/jpie/controller/error_handling.rb +0 -23
  74. data/lib/jpie/controller/json_api_validation.rb +0 -193
  75. data/lib/jpie/controller/parameter_parsing.rb +0 -78
  76. data/lib/jpie/controller/related_actions.rb +0 -45
  77. data/lib/jpie/controller/relationship_actions.rb +0 -291
  78. data/lib/jpie/controller/relationship_validation.rb +0 -117
  79. data/lib/jpie/controller/rendering.rb +0 -154
  80. data/lib/jpie/controller.rb +0 -45
  81. data/lib/jpie/deserializer.rb +0 -110
  82. data/lib/jpie/errors.rb +0 -117
  83. data/lib/jpie/generators/resource_generator.rb +0 -116
  84. data/lib/jpie/generators/templates/resource.rb.erb +0 -31
  85. data/lib/jpie/railtie.rb +0 -42
  86. data/lib/jpie/resource/attributable.rb +0 -112
  87. data/lib/jpie/resource/inferrable.rb +0 -43
  88. data/lib/jpie/resource/sortable.rb +0 -93
  89. data/lib/jpie/resource.rb +0 -147
  90. data/lib/jpie/routing.rb +0 -59
  91. data/lib/jpie/serializer.rb +0 -205
@@ -1,303 +0,0 @@
1
- # Pagination Example
2
-
3
- This example demonstrates how to implement pagination with JPie resources using both simple and JSON:API standard pagination parameters.
4
-
5
- ## Setup
6
-
7
- ### 1. Model (`app/models/article.rb`)
8
- ```ruby
9
- class Article < ActiveRecord::Base
10
- validates :title, presence: true
11
- validates :content, presence: true
12
- end
13
- ```
14
-
15
- ### 2. Resource (`app/resources/article_resource.rb`)
16
- ```ruby
17
- class ArticleResource < JPie::Resource
18
- attributes :title, :content, :published_at
19
- end
20
- ```
21
-
22
- ### 3. Controller (`app/controllers/articles_controller.rb`)
23
- ```ruby
24
- class ArticlesController < ApplicationController
25
- include JPie::Controller
26
- end
27
- ```
28
-
29
- ### 4. Routes (`config/routes.rb`)
30
- ```ruby
31
- Rails.application.routes.draw do
32
- resources :articles
33
- end
34
- ```
35
-
36
- ## HTTP Examples
37
-
38
- ### Simple Pagination Parameters
39
-
40
- #### Get First Page with 5 Articles
41
- ```http
42
- GET /articles?page=1&per_page=5
43
- Accept: application/vnd.api+json
44
-
45
- HTTP/1.1 200 OK
46
- Content-Type: application/vnd.api+json
47
-
48
- {
49
- "data": [
50
- {
51
- "id": "1",
52
- "type": "articles",
53
- "attributes": {
54
- "title": "First Article",
55
- "content": "Content of first article",
56
- "published_at": "2024-01-01T10:00:00Z"
57
- }
58
- },
59
- {
60
- "id": "2",
61
- "type": "articles",
62
- "attributes": {
63
- "title": "Second Article",
64
- "content": "Content of second article",
65
- "published_at": "2024-01-02T10:00:00Z"
66
- }
67
- }
68
- ],
69
- "meta": {
70
- "pagination": {
71
- "page": 1,
72
- "per_page": 5,
73
- "total_pages": 4,
74
- "total_count": 20
75
- }
76
- },
77
- "links": {
78
- "self": "http://example.com/articles?page=1&per_page=5",
79
- "first": "http://example.com/articles?page=1&per_page=5",
80
- "last": "http://example.com/articles?page=4&per_page=5",
81
- "next": "http://example.com/articles?page=2&per_page=5"
82
- }
83
- }
84
- ```
85
-
86
- #### Get Second Page
87
- ```http
88
- GET /articles?page=2&per_page=5
89
- Accept: application/vnd.api+json
90
-
91
- HTTP/1.1 200 OK
92
- Content-Type: application/vnd.api+json
93
-
94
- {
95
- "data": [
96
- {
97
- "id": "6",
98
- "type": "articles",
99
- "attributes": {
100
- "title": "Sixth Article",
101
- "content": "Content of sixth article",
102
- "published_at": "2024-01-06T10:00:00Z"
103
- }
104
- }
105
- ],
106
- "meta": {
107
- "pagination": {
108
- "page": 2,
109
- "per_page": 5,
110
- "total_pages": 4,
111
- "total_count": 20
112
- }
113
- },
114
- "links": {
115
- "self": "http://example.com/articles?page=2&per_page=5",
116
- "first": "http://example.com/articles?page=1&per_page=5",
117
- "last": "http://example.com/articles?page=4&per_page=5",
118
- "prev": "http://example.com/articles?page=1&per_page=5",
119
- "next": "http://example.com/articles?page=3&per_page=5"
120
- }
121
- }
122
- ```
123
-
124
- ### JSON:API Standard Pagination Parameters
125
-
126
- #### Get First Page Using JSON:API Format
127
- ```http
128
- GET /articles?page[number]=1&page[size]=3
129
- Accept: application/vnd.api+json
130
-
131
- HTTP/1.1 200 OK
132
- Content-Type: application/vnd.api+json
133
-
134
- {
135
- "data": [
136
- {
137
- "id": "1",
138
- "type": "articles",
139
- "attributes": {
140
- "title": "First Article",
141
- "content": "Content of first article",
142
- "published_at": "2024-01-01T10:00:00Z"
143
- }
144
- },
145
- {
146
- "id": "2",
147
- "type": "articles",
148
- "attributes": {
149
- "title": "Second Article",
150
- "content": "Content of second article",
151
- "published_at": "2024-01-02T10:00:00Z"
152
- }
153
- },
154
- {
155
- "id": "3",
156
- "type": "articles",
157
- "attributes": {
158
- "title": "Third Article",
159
- "content": "Content of third article",
160
- "published_at": "2024-01-03T10:00:00Z"
161
- }
162
- }
163
- ],
164
- "meta": {
165
- "pagination": {
166
- "page": 1,
167
- "per_page": 3,
168
- "total_pages": 7,
169
- "total_count": 20
170
- }
171
- },
172
- "links": {
173
- "self": "http://example.com/articles?page=1&per_page=3",
174
- "first": "http://example.com/articles?page=1&per_page=3",
175
- "last": "http://example.com/articles?page=7&per_page=3",
176
- "next": "http://example.com/articles?page=2&per_page=3"
177
- }
178
- }
179
- ```
180
-
181
- ### Pagination with Sorting
182
-
183
- #### Get Sorted and Paginated Results
184
- ```http
185
- GET /articles?sort=-published_at&page=1&per_page=3
186
- Accept: application/vnd.api+json
187
-
188
- HTTP/1.1 200 OK
189
- Content-Type: application/vnd.api+json
190
-
191
- {
192
- "data": [
193
- {
194
- "id": "20",
195
- "type": "articles",
196
- "attributes": {
197
- "title": "Latest Article",
198
- "content": "Most recent content",
199
- "published_at": "2024-01-20T10:00:00Z"
200
- }
201
- },
202
- {
203
- "id": "19",
204
- "type": "articles",
205
- "attributes": {
206
- "title": "Second Latest Article",
207
- "content": "Second most recent content",
208
- "published_at": "2024-01-19T10:00:00Z"
209
- }
210
- },
211
- {
212
- "id": "18",
213
- "type": "articles",
214
- "attributes": {
215
- "title": "Third Latest Article",
216
- "content": "Third most recent content",
217
- "published_at": "2024-01-18T10:00:00Z"
218
- }
219
- }
220
- ],
221
- "meta": {
222
- "pagination": {
223
- "page": 1,
224
- "per_page": 3,
225
- "total_pages": 7,
226
- "total_count": 20
227
- }
228
- },
229
- "links": {
230
- "self": "http://example.com/articles?sort=-published_at&page=1&per_page=3",
231
- "first": "http://example.com/articles?sort=-published_at&page=1&per_page=3",
232
- "last": "http://example.com/articles?sort=-published_at&page=7&per_page=3",
233
- "next": "http://example.com/articles?sort=-published_at&page=2&per_page=3"
234
- }
235
- }
236
- ```
237
-
238
- ### Last Page Response
239
-
240
- #### Get Last Page
241
- ```http
242
- GET /articles?page=4&per_page=5
243
- Accept: application/vnd.api+json
244
-
245
- HTTP/1.1 200 OK
246
- Content-Type: application/vnd.api+json
247
-
248
- {
249
- "data": [
250
- {
251
- "id": "20",
252
- "type": "articles",
253
- "attributes": {
254
- "title": "Last Article",
255
- "content": "Content of last article",
256
- "published_at": "2024-01-20T10:00:00Z"
257
- }
258
- }
259
- ],
260
- "meta": {
261
- "pagination": {
262
- "page": 4,
263
- "per_page": 5,
264
- "total_pages": 4,
265
- "total_count": 20
266
- }
267
- },
268
- "links": {
269
- "self": "http://example.com/articles?page=4&per_page=5",
270
- "first": "http://example.com/articles?page=1&per_page=5",
271
- "last": "http://example.com/articles?page=4&per_page=5",
272
- "prev": "http://example.com/articles?page=3&per_page=5"
273
- }
274
- }
275
- ```
276
-
277
- ### Empty Results
278
-
279
- #### Get Page Beyond Available Data
280
- ```http
281
- GET /articles?page=10&per_page=5
282
- Accept: application/vnd.api+json
283
-
284
- HTTP/1.1 200 OK
285
- Content-Type: application/vnd.api+json
286
-
287
- {
288
- "data": [],
289
- "meta": {
290
- "pagination": {
291
- "page": 10,
292
- "per_page": 5,
293
- "total_pages": 4,
294
- "total_count": 20
295
- }
296
- },
297
- "links": {
298
- "self": "http://example.com/articles?page=10&per_page=5",
299
- "first": "http://example.com/articles?page=1&per_page=5",
300
- "last": "http://example.com/articles?page=4&per_page=5"
301
- }
302
- }
303
- ```
@@ -1,114 +0,0 @@
1
- # JSON:API Relationship Management
2
-
3
- This example demonstrates how to manage relationships using JPie's JSON:API compliant relationship endpoints.
4
-
5
- ## Setup
6
-
7
- Define your resources with relationships:
8
-
9
- ```ruby
10
- # app/resources/user_resource.rb
11
- class UserResource < JPie::Resource
12
- model User
13
- attributes :name, :email
14
- has_many :posts
15
- end
16
-
17
- # app/resources/post_resource.rb
18
- class PostResource < JPie::Resource
19
- model Post
20
- attributes :title, :content
21
- has_one :author, resource: 'UserResource'
22
- end
23
-
24
- # app/controllers/users_controller.rb
25
- class UsersController < ApplicationController
26
- include JPie::Controller
27
- end
28
- ```
29
-
30
- Configure routes:
31
-
32
- ```ruby
33
- # config/routes.rb
34
- Rails.application.routes.draw do
35
- jpie_resources :users
36
- jpie_resources :posts
37
- end
38
- ```
39
-
40
- ## Relationship Operations
41
-
42
- ### Get Relationship Linkage
43
-
44
- ```http
45
- GET /users/1/relationships/posts
46
-
47
- Response:
48
- {
49
- "data": [
50
- { "type": "posts", "id": "1" },
51
- { "type": "posts", "id": "3" }
52
- ]
53
- }
54
- ```
55
-
56
- ### Replace Relationship
57
-
58
- ```http
59
- PATCH /users/1/relationships/posts
60
- Content-Type: application/vnd.api+json
61
-
62
- {
63
- "data": [
64
- { "type": "posts", "id": "2" },
65
- { "type": "posts", "id": "4" }
66
- ]
67
- }
68
- ```
69
-
70
- ### Add to Relationship
71
-
72
- ```http
73
- POST /users/1/relationships/posts
74
- Content-Type: application/vnd.api+json
75
-
76
- {
77
- "data": [
78
- { "type": "posts", "id": "5" }
79
- ]
80
- }
81
- ```
82
-
83
- ### Remove from Relationship
84
-
85
- ```http
86
- DELETE /users/1/relationships/posts
87
- Content-Type: application/vnd.api+json
88
-
89
- {
90
- "data": [
91
- { "type": "posts", "id": "2" }
92
- ]
93
- }
94
- ```
95
-
96
- ### Get Related Resources
97
-
98
- ```http
99
- GET /users/1/posts
100
-
101
- Response:
102
- {
103
- "data": [
104
- {
105
- "type": "posts",
106
- "id": "1",
107
- "attributes": {
108
- "title": "First Post",
109
- "content": "Hello world!"
110
- }
111
- }
112
- ]
113
- }
114
- ```
@@ -1,147 +0,0 @@
1
- # Resource Attribute Configuration Example
2
-
3
- This example demonstrates all the different ways to configure resource attributes in JPie, showcasing the various configuration patterns and customization techniques available for attributes.
4
-
5
- ## Setup
6
-
7
- ### 1. Model (`app/models/user.rb`)
8
- ```ruby
9
- class User < ActiveRecord::Base
10
- validates :first_name, presence: true
11
- validates :last_name, presence: true
12
- validates :email, presence: true, uniqueness: true
13
- validates :username, presence: true, uniqueness: true
14
-
15
- def active?
16
- true # Simple boolean for demonstration
17
- end
18
- end
19
- ```
20
-
21
- ### 2. Resource with All Attribute Configuration Types (`app/resources/user_resource.rb`)
22
- ```ruby
23
- class UserResource < JPie::Resource
24
- # 1. Basic attributes - direct model attribute access
25
- attributes :email, :first_name, :last_name
26
-
27
- # 2. Attribute with custom attr mapping (maps to different model attribute)
28
- attribute :display_name, attr: :username
29
-
30
- # 3. Attribute with block override
31
- attribute :status do
32
- object.active? ? 'active' : 'inactive'
33
- end
34
-
35
- # 4. Attribute with custom method override
36
- attribute :full_name
37
-
38
- private
39
-
40
- # Custom method for attribute override
41
- def full_name
42
- "#{object.first_name} #{object.last_name}".strip
43
- end
44
- end
45
- ```
46
-
47
- ### 3. Controller (`app/controllers/users_controller.rb`)
48
- ```ruby
49
- class UsersController < ApplicationController
50
- include JPie::Controller
51
- end
52
- ```
53
-
54
- ## HTTP Examples
55
-
56
- ### Create User
57
- ```http
58
- POST /users
59
- Content-Type: application/vnd.api+json
60
-
61
- {
62
- "data": {
63
- "type": "users",
64
- "attributes": {
65
- "email": "john.doe@example.com",
66
- "first_name": "John",
67
- "last_name": "Doe"
68
- }
69
- }
70
- }
71
-
72
- HTTP/1.1 201 Created
73
- Content-Type: application/vnd.api+json
74
-
75
- {
76
- "data": {
77
- "id": "1",
78
- "type": "users",
79
- "attributes": {
80
- "email": "john.doe@example.com",
81
- "first_name": "John",
82
- "last_name": "Doe",
83
- "display_name": "johndoe",
84
- "status": "active",
85
- "full_name": "John Doe"
86
- }
87
- }
88
- }
89
- ```
90
-
91
- ### Update User
92
- ```http
93
- PATCH /users/1
94
- Content-Type: application/vnd.api+json
95
-
96
- {
97
- "data": {
98
- "id": "1",
99
- "type": "users",
100
- "attributes": {
101
- "first_name": "Jonathan"
102
- }
103
- }
104
- }
105
-
106
- HTTP/1.1 200 OK
107
- Content-Type: application/vnd.api+json
108
-
109
- {
110
- "data": {
111
- "id": "1",
112
- "type": "users",
113
- "attributes": {
114
- "email": "john.doe@example.com",
115
- "first_name": "Jonathan",
116
- "last_name": "Doe",
117
- "display_name": "johndoe",
118
- "status": "active",
119
- "full_name": "Jonathan Doe"
120
- }
121
- }
122
- }
123
- ```
124
-
125
- ### Get User with All Attribute Configuration Types
126
- ```http
127
- GET /users/1
128
- Accept: application/vnd.api+json
129
-
130
- HTTP/1.1 200 OK
131
- Content-Type: application/vnd.api+json
132
-
133
- {
134
- "data": {
135
- "id": "1",
136
- "type": "users",
137
- "attributes": {
138
- "email": "john.doe@example.com",
139
- "first_name": "John",
140
- "last_name": "Doe",
141
- "display_name": "johndoe",
142
- "status": "active",
143
- "full_name": "John Doe"
144
- }
145
- }
146
- }
147
- ```