jsonapi-resources 0.0.16 → 0.1.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/README.md +44 -1
- data/lib/jsonapi/callbacks.rb +52 -0
- data/lib/jsonapi/operation.rb +1 -9
- data/lib/jsonapi/operations_processor.rb +20 -22
- data/lib/jsonapi/resource.rb +126 -28
- data/lib/jsonapi/resources/version.rb +1 -1
- data/lib/jsonapi/routing_ext.rb +17 -16
- data/test/fixtures/active_record.rb +34 -0
- data/test/unit/operation/operations_processor_test.rb +51 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9857d701e9136cba9b504cc0439b43e939722565
|
4
|
+
data.tar.gz: 5696329e4c5865e17b7b3bb0f6a40d4840a06f16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00981170f6a4d0743a298cc8478c9cf2e8d7cd07153a204fc878188a07aaeb79d3ed45529a2f3cc5a84dde326d2697b0faa880c619a9554e4689d0d60fb8f4c8
|
7
|
+
data.tar.gz: 8b42c9bdc12fc6b40aaec0e18b73d2871899047ce86ef77d8edf28e5775872337de9f83b4bc883d647fa4f563330a0987046c59ac4bf41f051d8f2f97a416e1e
|
data/README.md
CHANGED
@@ -124,7 +124,7 @@ class ContactResource < JSONAPI::Resource
|
|
124
124
|
super - [:full_name]
|
125
125
|
end
|
126
126
|
|
127
|
-
def self.createable_fields(
|
127
|
+
def self.createable_fields(context)
|
128
128
|
super - [:full_name]
|
129
129
|
end
|
130
130
|
end
|
@@ -330,6 +330,49 @@ class AuthorResource < JSONAPI::Resource
|
|
330
330
|
end
|
331
331
|
```
|
332
332
|
|
333
|
+
#### Callbacks
|
334
|
+
|
335
|
+
`ActiveSupport::Callbacks` is used to provide callback functionality, so the behavior is very similar to what you may be used to from `ActiveRecord`.
|
336
|
+
|
337
|
+
For example, you might use a callback to perform authorization on your resource before an action.
|
338
|
+
|
339
|
+
```ruby
|
340
|
+
class BaseResource < JSONAPI::Resource
|
341
|
+
before_create :authorize_create
|
342
|
+
|
343
|
+
def authorize_create
|
344
|
+
# ...
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
The types of supported callbacks are:
|
350
|
+
- `before`
|
351
|
+
- `after`
|
352
|
+
- `around`
|
353
|
+
|
354
|
+
##### `JSONAPI::Resource` Callbacks
|
355
|
+
|
356
|
+
Callbacks can be defined for the following `JSONAPI::Resource` events:
|
357
|
+
|
358
|
+
- `:create`
|
359
|
+
- `:update`
|
360
|
+
- `:remove`
|
361
|
+
- `:save`
|
362
|
+
- `:create_has_many_link`
|
363
|
+
- `:replace_has_many_links`
|
364
|
+
- `:create_has_one_link`
|
365
|
+
- `:replace_has_one_link`
|
366
|
+
- `:remove_has_many_link`
|
367
|
+
- `:remove_has_one_link`
|
368
|
+
- `:replace_fields`
|
369
|
+
|
370
|
+
##### `JSONAPI::OperationsProcessor` Callbacks
|
371
|
+
|
372
|
+
Callbacks can also be defined for `JSONAPI::OperationsProcessor` events:
|
373
|
+
- `:operations`: The set of operations.
|
374
|
+
- `:operation`: The individual operations.
|
375
|
+
|
333
376
|
### Controllers
|
334
377
|
|
335
378
|
`JSONAPI::Resources` provides a class, `ResourceController`, that can be used as the base class for your controllers. `ResourceController` supports `index`, `show`, `create`, `update`, and `destroy` methods. Just deriving your controller from `ResourceController` will give you a fully functional controller.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'active_support/callbacks'
|
2
|
+
|
3
|
+
module JSONAPI
|
4
|
+
module Callbacks
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
include ActiveSupport::Callbacks
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def define_jsonapi_resources_callbacks(*callbacks)
|
15
|
+
options = callbacks.extract_options!
|
16
|
+
options = {
|
17
|
+
only: [:before, :around, :after]
|
18
|
+
}.merge!(options)
|
19
|
+
|
20
|
+
types = Array(options.delete(:only))
|
21
|
+
|
22
|
+
callbacks.each do |callback|
|
23
|
+
define_callbacks(callback, options)
|
24
|
+
|
25
|
+
types.each do |type|
|
26
|
+
send("_define_#{type}_callback", self, callback)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def _define_before_callback(klass, callback) #:nodoc:
|
34
|
+
klass.define_singleton_method("before_#{callback}") do |*args, &block|
|
35
|
+
set_callback(:"#{callback}", :before, *args, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def _define_around_callback(klass, callback) #:nodoc:
|
40
|
+
klass.define_singleton_method("around_#{callback}") do |*args, &block|
|
41
|
+
set_callback(:"#{callback}", :around, *args, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _define_after_callback(klass, callback) #:nodoc:
|
46
|
+
klass.define_singleton_method("after_#{callback}") do |*args, &block|
|
47
|
+
set_callback(:"#{callback}", :after, *args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/jsonapi/operation.rb
CHANGED
@@ -22,7 +22,6 @@ module JSONAPI
|
|
22
22
|
def apply(context)
|
23
23
|
resource = @resource_klass.create(context)
|
24
24
|
resource.replace_fields(@values)
|
25
|
-
resource.save
|
26
25
|
|
27
26
|
return JSONAPI::OperationResult.new(:created, resource)
|
28
27
|
|
@@ -64,7 +63,6 @@ module JSONAPI
|
|
64
63
|
def apply(context)
|
65
64
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
66
65
|
resource.replace_fields(values)
|
67
|
-
resource.save
|
68
66
|
|
69
67
|
return JSONAPI::OperationResult.new(:ok, resource)
|
70
68
|
end
|
@@ -83,7 +81,6 @@ module JSONAPI
|
|
83
81
|
def apply(context)
|
84
82
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
85
83
|
resource.create_has_one_link(@association_type, @key_value)
|
86
|
-
resource.save
|
87
84
|
|
88
85
|
return JSONAPI::OperationResult.new(:no_content)
|
89
86
|
end
|
@@ -102,7 +99,6 @@ module JSONAPI
|
|
102
99
|
def apply(context)
|
103
100
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
104
101
|
resource.replace_has_one_link(@association_type, @key_value)
|
105
|
-
resource.save
|
106
102
|
|
107
103
|
return JSONAPI::OperationResult.new(:no_content)
|
108
104
|
end
|
@@ -120,9 +116,7 @@ module JSONAPI
|
|
120
116
|
|
121
117
|
def apply(context)
|
122
118
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
123
|
-
@key_values
|
124
|
-
resource.create_has_many_link(@association_type, value)
|
125
|
-
end
|
119
|
+
resource.create_has_many_links(@association_type, @key_values)
|
126
120
|
|
127
121
|
return JSONAPI::OperationResult.new(:no_content)
|
128
122
|
end
|
@@ -141,7 +135,6 @@ module JSONAPI
|
|
141
135
|
def apply(context)
|
142
136
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
143
137
|
resource.replace_has_many_links(@association_type, @key_values)
|
144
|
-
resource.save
|
145
138
|
|
146
139
|
return JSONAPI::OperationResult.new(:no_content)
|
147
140
|
end
|
@@ -180,7 +173,6 @@ module JSONAPI
|
|
180
173
|
def apply(context)
|
181
174
|
resource = @resource_klass.find_by_key(@resource_id, context: context)
|
182
175
|
resource.remove_has_one_link(@association_type)
|
183
|
-
resource.save
|
184
176
|
|
185
177
|
return JSONAPI::OperationResult.new(:no_content)
|
186
178
|
end
|
@@ -1,37 +1,35 @@
|
|
1
1
|
require 'jsonapi/operation_result'
|
2
|
+
require 'jsonapi/callbacks'
|
2
3
|
|
3
4
|
module JSONAPI
|
4
5
|
class OperationsProcessor
|
6
|
+
include Callbacks
|
7
|
+
define_jsonapi_resources_callbacks :operation, :operations
|
5
8
|
|
6
9
|
def process(request)
|
7
10
|
@results = []
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
@request = request
|
12
|
+
@context = request.context
|
13
|
+
@operations = request.operations
|
14
|
+
|
15
|
+
run_callbacks :operations do
|
16
|
+
transaction do
|
17
|
+
@operations.each do |operation|
|
18
|
+
@operation = operation
|
19
|
+
@result = nil
|
20
|
+
run_callbacks :operation do
|
21
|
+
@result = @operation.apply(@context)
|
22
|
+
@results.push(@result)
|
23
|
+
if @result.has_errors?
|
24
|
+
rollback
|
25
|
+
end
|
26
|
+
end
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
29
|
+
end
|
26
30
|
@results
|
27
31
|
end
|
28
32
|
|
29
|
-
def before_operation(context, operation)
|
30
|
-
end
|
31
|
-
|
32
|
-
def after_operation(context, result)
|
33
|
-
end
|
34
|
-
|
35
33
|
private
|
36
34
|
|
37
35
|
# The base OperationsProcessor provides no transaction support
|
data/lib/jsonapi/resource.rb
CHANGED
@@ -1,49 +1,154 @@
|
|
1
1
|
require 'jsonapi/configuration'
|
2
2
|
require 'jsonapi/resource_for'
|
3
3
|
require 'jsonapi/association'
|
4
|
+
require 'jsonapi/callbacks'
|
4
5
|
|
5
6
|
module JSONAPI
|
6
7
|
class Resource
|
7
8
|
include ResourceFor
|
9
|
+
include Callbacks
|
8
10
|
|
9
11
|
@@resource_types = {}
|
10
12
|
|
11
13
|
attr :context
|
12
14
|
attr_reader :model
|
13
15
|
|
16
|
+
define_jsonapi_resources_callbacks :create,
|
17
|
+
:update,
|
18
|
+
:remove,
|
19
|
+
:save,
|
20
|
+
:create_has_many_link,
|
21
|
+
:replace_has_many_links,
|
22
|
+
:create_has_one_link,
|
23
|
+
:replace_has_one_link,
|
24
|
+
:remove_has_many_link,
|
25
|
+
:remove_has_one_link,
|
26
|
+
:replace_fields
|
27
|
+
|
14
28
|
def initialize(model, context = nil)
|
15
29
|
@model = model
|
16
30
|
@context = context
|
17
31
|
end
|
18
32
|
|
19
|
-
def remove
|
20
|
-
@model.destroy
|
21
|
-
end
|
22
|
-
|
23
33
|
def id
|
24
34
|
model.send(self.class._primary_key)
|
25
35
|
end
|
26
36
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
37
|
+
def is_new?
|
38
|
+
id.nil?
|
39
|
+
end
|
30
40
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
41
|
+
def change(callback)
|
42
|
+
if @changing
|
43
|
+
run_callbacks callback do
|
44
|
+
yield
|
45
|
+
end
|
35
46
|
else
|
36
|
-
|
47
|
+
run_callbacks is_new? ? :create : :update do
|
48
|
+
@changing = true
|
49
|
+
run_callbacks callback do
|
50
|
+
yield
|
51
|
+
save if @save_needed
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove
|
58
|
+
run_callbacks :remove do
|
59
|
+
_remove
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_has_many_links(association_type, association_key_values)
|
64
|
+
change :create_has_many_link do
|
65
|
+
_create_has_many_links(association_type, association_key_values)
|
37
66
|
end
|
38
67
|
end
|
39
68
|
|
40
69
|
def replace_has_many_links(association_type, association_key_values)
|
70
|
+
change :replace_has_many_links do
|
71
|
+
_replace_has_many_links(association_type, association_key_values)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_has_one_link(association_type, association_key_value)
|
76
|
+
change :create_has_one_link do
|
77
|
+
_create_has_one_link(association_type, association_key_value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def replace_has_one_link(association_type, association_key_value)
|
82
|
+
change :replace_has_one_link do
|
83
|
+
_replace_has_one_link(association_type, association_key_value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def remove_has_many_link(association_type, key)
|
88
|
+
change :remove_has_many_link do
|
89
|
+
_remove_has_many_link(association_type, key)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def remove_has_one_link(association_type)
|
94
|
+
change :remove_has_one_link do
|
95
|
+
_remove_has_one_link(association_type)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def replace_fields(field_data)
|
100
|
+
change :replace_fields do
|
101
|
+
_replace_fields(field_data)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Override this on a resource instance to override the fetchable keys
|
106
|
+
def fetchable_fields
|
107
|
+
self.class.fields
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def save
|
112
|
+
run_callbacks :save do
|
113
|
+
_save
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def _save
|
118
|
+
@model.save!
|
119
|
+
@save_needed = false
|
120
|
+
rescue ActiveRecord::RecordInvalid => e
|
121
|
+
raise JSONAPI::Exceptions::ValidationErrors.new(e.record.errors.messages)
|
122
|
+
end
|
123
|
+
|
124
|
+
def _remove
|
125
|
+
@model.destroy
|
126
|
+
end
|
127
|
+
|
128
|
+
def _create_has_many_links(association_type, association_key_values)
|
129
|
+
association = self.class._associations[association_type]
|
130
|
+
|
131
|
+
association_key_values.each do |association_key_value|
|
132
|
+
related_resource = self.class.resource_for(association.type).find_by_key(association_key_value, context: @context)
|
133
|
+
|
134
|
+
# ToDo: Add option to skip relations that already exist instead of returning an error?
|
135
|
+
relation = @model.send(association.type).where(association.primary_key => association_key_value).first
|
136
|
+
if relation.nil?
|
137
|
+
@model.send(association.type) << related_resource.model
|
138
|
+
else
|
139
|
+
raise JSONAPI::Exceptions::HasManyRelationExists.new(association_key_value)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def _replace_has_many_links(association_type, association_key_values)
|
41
145
|
association = self.class._associations[association_type]
|
42
146
|
|
43
147
|
send("#{association.foreign_key}=", association_key_values)
|
148
|
+
@save_needed = true
|
44
149
|
end
|
45
150
|
|
46
|
-
def
|
151
|
+
def _create_has_one_link(association_type, association_key_value)
|
47
152
|
association = self.class._associations[association_type]
|
48
153
|
|
49
154
|
# ToDo: Add option to skip relations that already exist instead of returning an error?
|
@@ -53,30 +158,34 @@ module JSONAPI
|
|
53
158
|
else
|
54
159
|
raise JSONAPI::Exceptions::HasOneRelationExists.new
|
55
160
|
end
|
161
|
+
@save_needed = true
|
56
162
|
end
|
57
163
|
|
58
|
-
def
|
164
|
+
def _replace_has_one_link(association_type, association_key_value)
|
59
165
|
association = self.class._associations[association_type]
|
60
166
|
|
61
167
|
send("#{association.foreign_key}=", association_key_value)
|
168
|
+
@save_needed = true
|
62
169
|
end
|
63
170
|
|
64
|
-
def
|
171
|
+
def _remove_has_many_link(association_type, key)
|
65
172
|
association = self.class._associations[association_type]
|
66
173
|
|
67
174
|
@model.send(association.type).delete(key)
|
68
175
|
end
|
69
176
|
|
70
|
-
def
|
177
|
+
def _remove_has_one_link(association_type)
|
71
178
|
association = self.class._associations[association_type]
|
72
179
|
|
73
180
|
send("#{association.foreign_key}=", nil)
|
181
|
+
@save_needed = true
|
74
182
|
end
|
75
183
|
|
76
|
-
def
|
184
|
+
def _replace_fields(field_data)
|
77
185
|
field_data[:attributes].each do |attribute, value|
|
78
186
|
begin
|
79
187
|
send "#{attribute}=", value
|
188
|
+
@save_needed = true
|
80
189
|
rescue ArgumentError
|
81
190
|
# :nocov: Will be thrown if an enum value isn't allowed for an enum. Currently not tested as enums are a rails 4.1 and higher feature
|
82
191
|
raise JSONAPI::Exceptions::InvalidFieldValue.new(attribute, value)
|
@@ -97,17 +206,6 @@ module JSONAPI
|
|
97
206
|
end if field_data[:has_many]
|
98
207
|
end
|
99
208
|
|
100
|
-
def save
|
101
|
-
@model.save!
|
102
|
-
rescue ActiveRecord::RecordInvalid => e
|
103
|
-
raise JSONAPI::Exceptions::ValidationErrors.new(e.record.errors.messages)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Override this on a resource instance to override the fetchable keys
|
107
|
-
def fetchable_fields
|
108
|
-
self.class.fields
|
109
|
-
end
|
110
|
-
|
111
209
|
class << self
|
112
210
|
def inherited(base)
|
113
211
|
base._attributes = (_attributes || {}).dup
|
data/lib/jsonapi/routing_ext.rb
CHANGED
@@ -19,7 +19,7 @@ module ActionDispatch
|
|
19
19
|
|
20
20
|
def jsonapi_resource(*resources, &block)
|
21
21
|
resource_type = resources.first
|
22
|
-
res = JSONAPI::Resource.resource_for(
|
22
|
+
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(resources.first))
|
23
23
|
|
24
24
|
options = resources.extract_options!.dup
|
25
25
|
options[:controller] ||= resource_type
|
@@ -45,11 +45,7 @@ module ActionDispatch
|
|
45
45
|
|
46
46
|
def jsonapi_resources(*resources, &block)
|
47
47
|
resource_type = resources.first
|
48
|
-
|
49
|
-
@scope[:module],
|
50
|
-
resource_type
|
51
|
-
].compact.collect(&:to_s).join("/")
|
52
|
-
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
48
|
+
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix(resources.first))
|
53
49
|
|
54
50
|
options = resources.extract_options!.dup
|
55
51
|
options[:controller] ||= resource_type
|
@@ -93,28 +89,28 @@ module ActionDispatch
|
|
93
89
|
formatted_association_name = format_route(link_type)
|
94
90
|
options = links.extract_options!.dup
|
95
91
|
|
96
|
-
res = JSONAPI::Resource.resource_for(
|
92
|
+
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
97
93
|
|
98
94
|
methods = links_methods(options)
|
99
95
|
|
100
96
|
if methods.include?(:show)
|
101
97
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
102
|
-
|
98
|
+
action: 'show_association', association: link_type.to_s, via: [:get]
|
103
99
|
end
|
104
100
|
|
105
101
|
if methods.include?(:create)
|
106
102
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
107
|
-
|
103
|
+
action: 'create_association', association: link_type.to_s, via: [:post]
|
108
104
|
end
|
109
105
|
|
110
106
|
if methods.include?(:update)
|
111
107
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
112
|
-
|
108
|
+
action: 'update_association', association: link_type.to_s, via: [:put]
|
113
109
|
end
|
114
110
|
|
115
111
|
if methods.include?(:destroy)
|
116
112
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
117
|
-
|
113
|
+
action: 'destroy_association', association: link_type.to_s, via: [:delete]
|
118
114
|
end
|
119
115
|
end
|
120
116
|
|
@@ -123,30 +119,35 @@ module ActionDispatch
|
|
123
119
|
formatted_association_name = format_route(link_type)
|
124
120
|
options = links.extract_options!.dup
|
125
121
|
|
126
|
-
res = JSONAPI::Resource.resource_for(
|
122
|
+
res = JSONAPI::Resource.resource_for(resource_type_with_module_prefix)
|
127
123
|
|
128
124
|
methods = links_methods(options)
|
129
125
|
|
130
126
|
if methods.include?(:show)
|
131
127
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
132
|
-
|
128
|
+
action: 'show_association', association: link_type.to_s, via: [:get]
|
133
129
|
end
|
134
130
|
|
135
131
|
if methods.include?(:create)
|
136
132
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
137
|
-
|
133
|
+
action: 'create_association', association: link_type.to_s, via: [:post]
|
138
134
|
end
|
139
135
|
|
140
136
|
if methods.include?(:update) && res._association(link_type).acts_as_set
|
141
137
|
match "links/#{formatted_association_name}", controller: res._type.to_s,
|
142
|
-
|
138
|
+
action: 'update_association', association: link_type.to_s, via: [:put]
|
143
139
|
end
|
144
140
|
|
145
141
|
if methods.include?(:destroy)
|
146
142
|
match "links/#{formatted_association_name}/:keys", controller: res._type.to_s,
|
147
|
-
|
143
|
+
action: 'destroy_association', association: link_type.to_s, via: [:delete]
|
148
144
|
end
|
149
145
|
end
|
146
|
+
|
147
|
+
def resource_type_with_module_prefix(resource = nil)
|
148
|
+
resource_name = resource || @scope[:jsonapi_resource]
|
149
|
+
[@scope[:module], resource_name].compact.collect(&:to_s).join("/")
|
150
|
+
end
|
150
151
|
end
|
151
152
|
end
|
152
153
|
end
|
@@ -413,6 +413,39 @@ class PostResource < JSONAPI::Resource
|
|
413
413
|
has_one :section
|
414
414
|
has_many :tags, acts_as_set: true
|
415
415
|
has_many :comments, acts_as_set: false
|
416
|
+
|
417
|
+
before_save do
|
418
|
+
msg = "Before save"
|
419
|
+
end
|
420
|
+
|
421
|
+
after_save do
|
422
|
+
msg = "After save"
|
423
|
+
end
|
424
|
+
|
425
|
+
before_update do
|
426
|
+
msg = "Before update"
|
427
|
+
end
|
428
|
+
|
429
|
+
after_update do
|
430
|
+
msg = "After update"
|
431
|
+
end
|
432
|
+
|
433
|
+
before_replace_fields do
|
434
|
+
msg = "Before replace_fields"
|
435
|
+
end
|
436
|
+
|
437
|
+
after_replace_fields do
|
438
|
+
msg = "After replace_fields"
|
439
|
+
end
|
440
|
+
|
441
|
+
around_update :around_update_check
|
442
|
+
|
443
|
+
def around_update_check
|
444
|
+
# do nothing
|
445
|
+
yield
|
446
|
+
# do nothing
|
447
|
+
end
|
448
|
+
|
416
449
|
def subject
|
417
450
|
@model.title
|
418
451
|
end
|
@@ -606,6 +639,7 @@ end
|
|
606
639
|
module Api
|
607
640
|
module V3
|
608
641
|
PostResource = PostResource.dup
|
642
|
+
PreferencesResource = PreferencesResource.dup
|
609
643
|
end
|
610
644
|
end
|
611
645
|
|
@@ -5,6 +5,56 @@ require 'jsonapi/operation'
|
|
5
5
|
require 'jsonapi/operation_result'
|
6
6
|
require 'jsonapi/operations_processor'
|
7
7
|
|
8
|
+
class TestOperationsProcessor < JSONAPI::OperationsProcessor
|
9
|
+
before_operation :log_before_operation
|
10
|
+
|
11
|
+
after_operation :log_after_operation
|
12
|
+
|
13
|
+
around_operation :log_around_operation
|
14
|
+
|
15
|
+
def log_before_operation
|
16
|
+
msg = "Before Operation"
|
17
|
+
# puts msg
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_around_operation
|
21
|
+
msg = "Starting... #{@operation.class.name}"
|
22
|
+
# puts msg
|
23
|
+
yield
|
24
|
+
msg = "... Finishing #{@operation.class.name}"
|
25
|
+
# puts msg
|
26
|
+
end
|
27
|
+
|
28
|
+
def log_after_operation
|
29
|
+
msg = "After Operation"
|
30
|
+
# puts msg
|
31
|
+
end
|
32
|
+
|
33
|
+
before_operations :log_before_operations
|
34
|
+
|
35
|
+
after_operations :log_after_operations
|
36
|
+
|
37
|
+
around_operations :log_around_operations
|
38
|
+
|
39
|
+
def log_before_operations
|
40
|
+
msg = "Before #{@operations.count} Operation(s)"
|
41
|
+
# puts msg
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_around_operations
|
45
|
+
msg = "Starting #{@operations.count} Operation(s)..."
|
46
|
+
# puts msg
|
47
|
+
yield
|
48
|
+
msg = "...Finishing Up Operations"
|
49
|
+
# puts msg
|
50
|
+
end
|
51
|
+
|
52
|
+
def log_after_operations
|
53
|
+
msg = "After Operations"
|
54
|
+
# puts msg
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
8
58
|
class OperationsProcessorTest < MiniTest::Unit::TestCase
|
9
59
|
def setup
|
10
60
|
betax = Planet.find(5)
|
@@ -14,7 +64,7 @@ class OperationsProcessorTest < MiniTest::Unit::TestCase
|
|
14
64
|
end
|
15
65
|
|
16
66
|
def test_create_single_resource
|
17
|
-
op =
|
67
|
+
op = TestOperationsProcessor.new()
|
18
68
|
|
19
69
|
count = Planet.count
|
20
70
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi-resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Gebhardt
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-01-
|
12
|
+
date: 2015-01-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -128,6 +128,7 @@ files:
|
|
128
128
|
- lib/jsonapi-resources.rb
|
129
129
|
- lib/jsonapi/active_record_operations_processor.rb
|
130
130
|
- lib/jsonapi/association.rb
|
131
|
+
- lib/jsonapi/callbacks.rb
|
131
132
|
- lib/jsonapi/configuration.rb
|
132
133
|
- lib/jsonapi/error.rb
|
133
134
|
- lib/jsonapi/error_codes.rb
|