jsonapi-resources 0.0.16 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|