jsonapi_compliable 0.6.4 → 0.6.5
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 +1 -1
- data/.travis.yml +11 -3
- data/.yardopts +1 -0
- data/README.md +10 -1
- data/Rakefile +1 -0
- data/docs/JsonapiCompliable.html +202 -0
- data/docs/JsonapiCompliable/Adapters.html +119 -0
- data/docs/JsonapiCompliable/Adapters/Abstract.html +2285 -0
- data/docs/JsonapiCompliable/Adapters/ActiveRecord.html +2151 -0
- data/docs/JsonapiCompliable/Adapters/ActiveRecordSideloading.html +582 -0
- data/docs/JsonapiCompliable/Adapters/Null.html +1682 -0
- data/docs/JsonapiCompliable/Base.html +1395 -0
- data/docs/JsonapiCompliable/Deserializer.html +835 -0
- data/docs/JsonapiCompliable/Errors.html +115 -0
- data/docs/JsonapiCompliable/Errors/BadFilter.html +124 -0
- data/docs/JsonapiCompliable/Errors/StatNotFound.html +266 -0
- data/docs/JsonapiCompliable/Errors/UnsupportedPageSize.html +264 -0
- data/docs/JsonapiCompliable/Errors/ValidationError.html +124 -0
- data/docs/JsonapiCompliable/Extensions.html +117 -0
- data/docs/JsonapiCompliable/Extensions/BooleanAttribute.html +212 -0
- data/docs/JsonapiCompliable/Extensions/BooleanAttribute/ClassMethods.html +229 -0
- data/docs/JsonapiCompliable/Extensions/ExtraAttribute.html +242 -0
- data/docs/JsonapiCompliable/Extensions/ExtraAttribute/ClassMethods.html +237 -0
- data/docs/JsonapiCompliable/Query.html +1099 -0
- data/docs/JsonapiCompliable/Rails.html +211 -0
- data/docs/JsonapiCompliable/Resource.html +5241 -0
- data/docs/JsonapiCompliable/Scope.html +703 -0
- data/docs/JsonapiCompliable/Scoping.html +117 -0
- data/docs/JsonapiCompliable/Scoping/Base.html +843 -0
- data/docs/JsonapiCompliable/Scoping/DefaultFilter.html +318 -0
- data/docs/JsonapiCompliable/Scoping/ExtraFields.html +301 -0
- data/docs/JsonapiCompliable/Scoping/Filter.html +313 -0
- data/docs/JsonapiCompliable/Scoping/Filterable.html +364 -0
- data/docs/JsonapiCompliable/Scoping/Paginate.html +613 -0
- data/docs/JsonapiCompliable/Scoping/Sort.html +454 -0
- data/docs/JsonapiCompliable/SerializableTempId.html +216 -0
- data/docs/JsonapiCompliable/Sideload.html +2484 -0
- data/docs/JsonapiCompliable/Stats.html +117 -0
- data/docs/JsonapiCompliable/Stats/DSL.html +999 -0
- data/docs/JsonapiCompliable/Stats/Payload.html +391 -0
- data/docs/JsonapiCompliable/Util.html +117 -0
- data/docs/JsonapiCompliable/Util/FieldParams.html +228 -0
- data/docs/JsonapiCompliable/Util/Hash.html +471 -0
- data/docs/JsonapiCompliable/Util/IncludeParams.html +299 -0
- data/docs/JsonapiCompliable/Util/Persistence.html +435 -0
- data/docs/JsonapiCompliable/Util/RelationshipPayload.html +563 -0
- data/docs/JsonapiCompliable/Util/RenderOptions.html +250 -0
- data/docs/JsonapiCompliable/Util/ValidationResponse.html +532 -0
- data/docs/_index.html +527 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +492 -0
- data/docs/file.README.html +99 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +99 -0
- data/docs/js/app.js +248 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +1731 -0
- data/docs/top-level-namespace.html +110 -0
- data/gemfiles/rails_5.gemfile +1 -1
- data/lib/jsonapi_compliable/adapters/abstract.rb +267 -4
- data/lib/jsonapi_compliable/adapters/active_record.rb +23 -1
- data/lib/jsonapi_compliable/adapters/null.rb +43 -3
- data/lib/jsonapi_compliable/base.rb +182 -33
- data/lib/jsonapi_compliable/deserializer.rb +90 -21
- data/lib/jsonapi_compliable/extensions/boolean_attribute.rb +12 -0
- data/lib/jsonapi_compliable/extensions/extra_attribute.rb +32 -0
- data/lib/jsonapi_compliable/extensions/temp_id.rb +11 -0
- data/lib/jsonapi_compliable/query.rb +94 -2
- data/lib/jsonapi_compliable/rails.rb +8 -0
- data/lib/jsonapi_compliable/resource.rb +548 -11
- data/lib/jsonapi_compliable/scope.rb +43 -1
- data/lib/jsonapi_compliable/scoping/base.rb +59 -8
- data/lib/jsonapi_compliable/scoping/default_filter.rb +33 -0
- data/lib/jsonapi_compliable/scoping/extra_fields.rb +33 -0
- data/lib/jsonapi_compliable/scoping/filter.rb +29 -2
- data/lib/jsonapi_compliable/scoping/filterable.rb +4 -0
- data/lib/jsonapi_compliable/scoping/paginate.rb +33 -0
- data/lib/jsonapi_compliable/scoping/sort.rb +18 -0
- data/lib/jsonapi_compliable/sideload.rb +229 -1
- data/lib/jsonapi_compliable/stats/dsl.rb +44 -0
- data/lib/jsonapi_compliable/stats/payload.rb +20 -0
- data/lib/jsonapi_compliable/util/field_params.rb +1 -0
- data/lib/jsonapi_compliable/util/hash.rb +18 -0
- data/lib/jsonapi_compliable/util/include_params.rb +22 -0
- data/lib/jsonapi_compliable/util/persistence.rb +13 -3
- data/lib/jsonapi_compliable/util/relationship_payload.rb +2 -0
- data/lib/jsonapi_compliable/util/render_options.rb +2 -0
- data/lib/jsonapi_compliable/util/validation_response.rb +16 -0
- data/lib/jsonapi_compliable/version.rb +1 -1
- metadata +60 -5
- data/gemfiles/rails_4.gemfile.lock +0 -208
- data/gemfiles/rails_5.gemfile.lock +0 -212
- data/lib/jsonapi_compliable/write.rb +0 -93
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>
|
|
7
|
+
Top Level Namespace
|
|
8
|
+
|
|
9
|
+
— Documentation by YARD 0.9.9
|
|
10
|
+
|
|
11
|
+
</title>
|
|
12
|
+
|
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
|
14
|
+
|
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
|
16
|
+
|
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
|
18
|
+
pathId = "";
|
|
19
|
+
relpath = '';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
|
24
|
+
|
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<div class="nav_wrap">
|
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
|
32
|
+
<div id="resizer"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div id="main" tabindex="-1">
|
|
36
|
+
<div id="header">
|
|
37
|
+
<div id="menu">
|
|
38
|
+
|
|
39
|
+
<a href="_index.html">Index</a> »
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
<span class="title">Top Level Namespace</span>
|
|
43
|
+
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div id="search">
|
|
47
|
+
|
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
|
49
|
+
href="class_list.html">
|
|
50
|
+
|
|
51
|
+
<svg width="24" height="24">
|
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
|
55
|
+
</svg>
|
|
56
|
+
</a>
|
|
57
|
+
|
|
58
|
+
</div>
|
|
59
|
+
<div class="clear"></div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
</h1>
|
|
67
|
+
<div class="box_info">
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<h2>Defined Under Namespace</h2>
|
|
82
|
+
<p class="children">
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="JsonapiCompliable.html" title="JsonapiCompliable (module)">JsonapiCompliable</a></span>
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
</p>
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div id="footer">
|
|
103
|
+
Generated on Fri May 5 15:53:21 2017 by
|
|
104
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
105
|
+
0.9.9 (ruby-2.3.0).
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
</div>
|
|
109
|
+
</body>
|
|
110
|
+
</html>
|
data/gemfiles/rails_5.gemfile
CHANGED
|
@@ -1,33 +1,296 @@
|
|
|
1
1
|
module JsonapiCompliable
|
|
2
2
|
module Adapters
|
|
3
|
+
# Adapters DRY up common resource logic.
|
|
4
|
+
#
|
|
5
|
+
# For instance, there's no reason to write ActiveRecord logic like this in
|
|
6
|
+
# every Resource:
|
|
7
|
+
#
|
|
8
|
+
# allow_filter :title do |scope, value|
|
|
9
|
+
# scope.where(title: value)
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# sort do |scope, att, dir|
|
|
13
|
+
# scope.order(att => dir)
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# paginate do |scope, current_page, per_page|
|
|
17
|
+
# scope.page(current_page).per(per_page)
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# This logic can be re-used through an *Adapter*:
|
|
21
|
+
#
|
|
22
|
+
# use_adapter JsonapiCompliable::Adapters::ActiveRecord
|
|
23
|
+
# allow_filter :title
|
|
24
|
+
#
|
|
25
|
+
# Adapters are pretty simple to write. The corresponding code for the above
|
|
26
|
+
# ActiveRecord adapter, which should look pretty familiar:
|
|
27
|
+
#
|
|
28
|
+
# class JsonapiCompliable::Adapters::ActiveRecord
|
|
29
|
+
# def filter(scope, attribute, value)
|
|
30
|
+
# scope.where(attribute => value)
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# def order(scope, attribute, direction)
|
|
34
|
+
# scope.order(attribute => direction)
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# def paginate(scope, current_page, per_page)
|
|
38
|
+
# scope.page(current_page).per(per_page)
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# An adapter can have a corresponding +sideloading_module+. This module
|
|
43
|
+
# gets mixed in to a Sideload. In other words, *Resource* is to
|
|
44
|
+
# *Adapter* as *Sideload* is to *Adapter#sideloading_module*. Use this
|
|
45
|
+
# module to define DSL methods that wrap #allow_sideload:
|
|
46
|
+
#
|
|
47
|
+
# class MyAdapter < JsonapiCompliable::Adapters::Abstract
|
|
48
|
+
# # ... code ...
|
|
49
|
+
# def sideloading_module
|
|
50
|
+
# MySideloadingAdapter
|
|
51
|
+
# end
|
|
52
|
+
# end
|
|
53
|
+
#
|
|
54
|
+
# module MySideloadingAdapter
|
|
55
|
+
# def belongs_to(association_name)
|
|
56
|
+
# allow_sideload association_name do
|
|
57
|
+
# # ... code ...
|
|
58
|
+
# end
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
# # And now in your Resource:
|
|
63
|
+
# class MyResource < ApplicationResource
|
|
64
|
+
# # ... code ...
|
|
65
|
+
# use_adapter MyAdapter
|
|
66
|
+
#
|
|
67
|
+
# belongs_to :my_association
|
|
68
|
+
# end
|
|
69
|
+
#
|
|
70
|
+
# If you need the adapter to do *nothing*, because perhaps the API you
|
|
71
|
+
# are hitting does not support sorting,
|
|
72
|
+
# use +JsonapiCompliable::Adapters::Null+.
|
|
73
|
+
#
|
|
74
|
+
# @see Resource.use_adapter
|
|
75
|
+
# @see Adapters::ActiveRecord
|
|
76
|
+
# @see Adapters::ActiveRecordSideloading
|
|
77
|
+
# @see Adapters::Null
|
|
3
78
|
class Abstract
|
|
79
|
+
# @param scope The scope object we are chaining
|
|
80
|
+
# @param [Symbol] attribute The attribute name we are filtering
|
|
81
|
+
# @param value The corresponding query parameter value
|
|
82
|
+
# @return the scope
|
|
83
|
+
#
|
|
84
|
+
# @example ActiveRecord default
|
|
85
|
+
# def filter(scope, attribute, value)
|
|
86
|
+
# scope.where(attribute => value)
|
|
87
|
+
# end
|
|
4
88
|
def filter(scope, attribute, value)
|
|
5
89
|
raise 'you must override #filter in an adapter subclass'
|
|
6
90
|
end
|
|
7
91
|
|
|
92
|
+
# @param scope The scope object we are chaining
|
|
93
|
+
# @param [Symbol] attribute The attribute name we are sorting
|
|
94
|
+
# @param [Symbol] direction The direction we are sorting (asc/desc)
|
|
95
|
+
# @return the scope
|
|
96
|
+
#
|
|
97
|
+
# @example ActiveRecord default
|
|
98
|
+
# def order(scope, attribute, direction)
|
|
99
|
+
# scope.order(attribute => direction)
|
|
100
|
+
# end
|
|
8
101
|
def order(scope, attribute, direction)
|
|
9
102
|
raise 'you must override #order in an adapter subclass'
|
|
10
103
|
end
|
|
11
104
|
|
|
12
|
-
|
|
105
|
+
# @param scope The scope object we are chaining
|
|
106
|
+
# @param [Integer] current_page The current page number
|
|
107
|
+
# @param [Integer] per_page The number of results per page
|
|
108
|
+
# @return the scope
|
|
109
|
+
#
|
|
110
|
+
# @example ActiveRecord default
|
|
111
|
+
# # via kaminari gem
|
|
112
|
+
# def paginate(scope, current_page, per_page)
|
|
113
|
+
# scope.page(current_page).per(per_page)
|
|
114
|
+
# end
|
|
115
|
+
def paginate(scope, current_page, per_page)
|
|
13
116
|
raise 'you must override #paginate in an adapter subclass'
|
|
14
117
|
end
|
|
15
118
|
|
|
16
|
-
|
|
17
|
-
|
|
119
|
+
# @param scope the scope object we are chaining
|
|
120
|
+
# @param [Symbol] attr corresponding stat attribute name
|
|
121
|
+
# @return [Numeric] the count of the scope
|
|
122
|
+
# @example ActiveRecord default
|
|
123
|
+
# def count(scope, attr)
|
|
124
|
+
# column = attr == :total ? :all : attr
|
|
125
|
+
# scope.uniq.count(column)
|
|
126
|
+
# end
|
|
127
|
+
def count(scope, attr)
|
|
128
|
+
raise 'you must override #count in an adapter subclass'
|
|
18
129
|
end
|
|
19
130
|
|
|
20
|
-
|
|
131
|
+
# @param scope the scope object we are chaining
|
|
132
|
+
# @param [Symbol] attr corresponding stat attribute name
|
|
133
|
+
# @return [Float] the average of the scope
|
|
134
|
+
# @example ActiveRecord default
|
|
135
|
+
# def average(scope, attr)
|
|
136
|
+
# scope.average(attr).to_f
|
|
137
|
+
# end
|
|
138
|
+
def average(scope, attr)
|
|
139
|
+
raise 'you must override #average in an adapter subclass'
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @param scope the scope object we are chaining
|
|
143
|
+
# @param [Symbol] attr corresponding stat attribute name
|
|
144
|
+
# @return [Numeric] the sum of the scope
|
|
145
|
+
# @example ActiveRecord default
|
|
146
|
+
# def sum(scope, attr)
|
|
147
|
+
# scope.sum(attr)
|
|
148
|
+
# end
|
|
149
|
+
def sum(scope, attr)
|
|
150
|
+
raise 'you must override #sum in an adapter subclass'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# @param scope the scope object we are chaining
|
|
154
|
+
# @param [Symbol] attr corresponding stat attribute name
|
|
155
|
+
# @return [Numeric] the maximum value of the scope
|
|
156
|
+
# @example ActiveRecord default
|
|
157
|
+
# def maximum(scope, attr)
|
|
158
|
+
# scope.maximum(attr)
|
|
159
|
+
# end
|
|
160
|
+
def maximum(scope, attr)
|
|
161
|
+
raise 'you must override #maximum in an adapter subclass'
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @param scope the scope object we are chaining
|
|
165
|
+
# @param [Symbol] attr corresponding stat attribute name
|
|
166
|
+
# @return [Numeric] the maximum value of the scope
|
|
167
|
+
# @example ActiveRecord default
|
|
168
|
+
# def maximum(scope, attr)
|
|
169
|
+
# scope.maximum(attr)
|
|
170
|
+
# end
|
|
171
|
+
def minimum(scope, attr)
|
|
172
|
+
raise 'you must override #maximum in an adapter subclass'
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# This method must +yield+ the code to run within the transaction.
|
|
176
|
+
# This method should roll back the transaction if an error is raised.
|
|
177
|
+
#
|
|
178
|
+
# @param [Class] model_class The class we're operating on
|
|
179
|
+
# @example ActiveRecord default
|
|
180
|
+
# def transaction(model_class)
|
|
181
|
+
# model_class.transaction do
|
|
182
|
+
# yield
|
|
183
|
+
# end
|
|
184
|
+
# end
|
|
185
|
+
#
|
|
186
|
+
# @see Resource.model
|
|
187
|
+
def transaction(model_class)
|
|
21
188
|
raise 'you must override #transaction in an adapter subclass, it must yield'
|
|
22
189
|
end
|
|
23
190
|
|
|
191
|
+
# Resolve the scope. This is where you'd actually fire SQL,
|
|
192
|
+
# actually make an HTTP call, etc.
|
|
193
|
+
#
|
|
194
|
+
# @example ActiveRecordDefault
|
|
195
|
+
# def resolve(scope)
|
|
196
|
+
# scope.to_a
|
|
197
|
+
# end
|
|
198
|
+
#
|
|
199
|
+
# @example Suggested Customization
|
|
200
|
+
# # When making a service call, we suggest this abstraction
|
|
201
|
+
# # 'scope' here is a hash
|
|
202
|
+
# def resolve(scope)
|
|
203
|
+
# # The implementation of .where can be whatever you want
|
|
204
|
+
# SomeModelClass.where(scope)
|
|
205
|
+
# end
|
|
206
|
+
#
|
|
207
|
+
# @see Adapters::ActiveRecord#resolve
|
|
208
|
+
# @param scope The scope object to resolve
|
|
209
|
+
# @return an array of Model instances
|
|
24
210
|
def resolve(scope)
|
|
25
211
|
scope
|
|
26
212
|
end
|
|
27
213
|
|
|
214
|
+
# Assign these two objects together.
|
|
215
|
+
#
|
|
216
|
+
# @example Basic accessor
|
|
217
|
+
# def associate(parent, child, association_name, association_type)
|
|
218
|
+
# if association_type == :has_many
|
|
219
|
+
# parent.send(association_name).push(child)
|
|
220
|
+
# else
|
|
221
|
+
# child.send(:"#{association_name}=", parent)
|
|
222
|
+
# end
|
|
223
|
+
# end
|
|
224
|
+
#
|
|
225
|
+
# +association_name+ and +association_type+ come from your sideload
|
|
226
|
+
# configuration:
|
|
227
|
+
#
|
|
228
|
+
# allow_sideload :the_name, type: the_type do
|
|
229
|
+
# # ... code.
|
|
230
|
+
# end
|
|
231
|
+
#
|
|
232
|
+
# @param parent The parent object (via the JSONAPI 'relationships' graph)
|
|
233
|
+
# @param child The child object (via the JSONAPI 'relationships' graph)
|
|
234
|
+
# @param association_name The 'relationships' key we are processing
|
|
235
|
+
# @param association_type The Sideload type (see Sideload#type). Usually :has_many/:belongs_to/etc
|
|
236
|
+
def associate(parent, child, association_name, association_type)
|
|
237
|
+
raise 'you must override #associate in an adapter subclass'
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# This module gets mixed in to Sideload classes
|
|
241
|
+
# This is where you define methods like has_many,
|
|
242
|
+
# belongs_to etc that wrap the lower-level Sideload#allow_sideload
|
|
243
|
+
#
|
|
244
|
+
# @see Resource#allow_sideload
|
|
245
|
+
# @see Sideload#allow_sideload
|
|
246
|
+
# @see Adapters::ActiveRecord#sideloading_module
|
|
247
|
+
# @see Adapters::ActiveRecordSideloading
|
|
248
|
+
# @return the module to mix in
|
|
28
249
|
def sideloading_module
|
|
29
250
|
Module.new
|
|
30
251
|
end
|
|
252
|
+
|
|
253
|
+
# @param [Class] model_class The configured model class (see Resource.model)
|
|
254
|
+
# @param [Hash] create_params Attributes + id
|
|
255
|
+
# @return the model instance just created
|
|
256
|
+
# @see Resource.model
|
|
257
|
+
# @example ActiveRecord default
|
|
258
|
+
# def create(model_class, create_params)
|
|
259
|
+
# instance = model_class.new(create_params)
|
|
260
|
+
# instance.save
|
|
261
|
+
# instance
|
|
262
|
+
# end
|
|
263
|
+
def create(model_class, create_params)
|
|
264
|
+
raise 'you must override #create in an adapter subclass'
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# @param [Class] model_class The configured model class (see Resource.model)
|
|
268
|
+
# @param [Hash] update_params Attributes + id
|
|
269
|
+
# @return the model instance just created
|
|
270
|
+
# @see Resource.model
|
|
271
|
+
# @example ActiveRecord default
|
|
272
|
+
# def update(model_class, update_params)
|
|
273
|
+
# instance = model_class.find(update_params.delete(:id))
|
|
274
|
+
# instance.update_attributes(update_params)
|
|
275
|
+
# instance
|
|
276
|
+
# end
|
|
277
|
+
def update(model_class, update_params)
|
|
278
|
+
raise 'you must override #update in an adapter subclass'
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# @param [Class] model_class The configured model class (see Resource.model)
|
|
282
|
+
# @param [Integer] id the id for this model
|
|
283
|
+
# @return the model instance just destroyed
|
|
284
|
+
# @see Resource.model
|
|
285
|
+
# @example ActiveRecord default
|
|
286
|
+
# def destroy(model_class, id)
|
|
287
|
+
# instance = model_class.find(id)
|
|
288
|
+
# instance.destroy
|
|
289
|
+
# instance
|
|
290
|
+
# end
|
|
291
|
+
def destroy(model_class, id)
|
|
292
|
+
raise 'you must override #destroy in an adapter subclass'
|
|
293
|
+
end
|
|
31
294
|
end
|
|
32
295
|
end
|
|
33
296
|
end
|
|
@@ -2,53 +2,72 @@ require 'jsonapi_compliable/adapters/active_record_sideloading'
|
|
|
2
2
|
|
|
3
3
|
module JsonapiCompliable
|
|
4
4
|
module Adapters
|
|
5
|
+
# @see Adapters::Abstract
|
|
5
6
|
class ActiveRecord < Abstract
|
|
7
|
+
# (see Adapters::Abstract#filter)
|
|
6
8
|
def filter(scope, attribute, value)
|
|
7
9
|
scope.where(attribute => value)
|
|
8
10
|
end
|
|
9
11
|
|
|
12
|
+
# (see Adapters::Abstract#order)
|
|
10
13
|
def order(scope, attribute, direction)
|
|
11
14
|
scope.order(attribute => direction)
|
|
12
15
|
end
|
|
13
16
|
|
|
17
|
+
# (see Adapters::Abstract#paginate)
|
|
14
18
|
def paginate(scope, current_page, per_page)
|
|
15
19
|
scope.page(current_page).per(per_page)
|
|
16
20
|
end
|
|
17
21
|
|
|
22
|
+
# (see Adapters::Abstract#count)
|
|
18
23
|
def count(scope, attr)
|
|
19
|
-
|
|
24
|
+
column = attr == :total ? :all : attr
|
|
25
|
+
scope.uniq.count(column)
|
|
20
26
|
end
|
|
21
27
|
|
|
28
|
+
# (see Adapters::Abstract#average)
|
|
22
29
|
def average(scope, attr)
|
|
23
30
|
scope.average(attr).to_f
|
|
24
31
|
end
|
|
25
32
|
|
|
33
|
+
# (see Adapters::Abstract#sum)
|
|
26
34
|
def sum(scope, attr)
|
|
27
35
|
scope.sum(attr)
|
|
28
36
|
end
|
|
29
37
|
|
|
38
|
+
# (see Adapters::Abstract#maximum)
|
|
30
39
|
def maximum(scope, attr)
|
|
31
40
|
scope.maximum(attr)
|
|
32
41
|
end
|
|
33
42
|
|
|
43
|
+
# (see Adapters::Abstract#minimum)
|
|
34
44
|
def minimum(scope, attr)
|
|
35
45
|
scope.minimum(attr)
|
|
36
46
|
end
|
|
37
47
|
|
|
48
|
+
# (see Adapters::Abstract#resolve)
|
|
38
49
|
def resolve(scope)
|
|
39
50
|
scope.to_a
|
|
40
51
|
end
|
|
41
52
|
|
|
53
|
+
# Run this write request within an ActiveRecord transaction
|
|
54
|
+
# @param [Class] model_class The ActiveRecord class we are saving
|
|
55
|
+
# @return Result of yield
|
|
56
|
+
# @see Adapters::Abstract#transaction
|
|
42
57
|
def transaction(model_class)
|
|
43
58
|
model_class.transaction do
|
|
44
59
|
yield
|
|
45
60
|
end
|
|
46
61
|
end
|
|
47
62
|
|
|
63
|
+
# (see Adapters::Abstract#sideloading_module)
|
|
48
64
|
def sideloading_module
|
|
49
65
|
JsonapiCompliable::Adapters::ActiveRecordSideloading
|
|
50
66
|
end
|
|
51
67
|
|
|
68
|
+
# When a has_many relationship, we need to avoid Activerecord implicitly
|
|
69
|
+
# firing a query. Otherwise, simple assignment will do
|
|
70
|
+
# @see Adapters::Abstract#associate
|
|
52
71
|
def associate(parent, child, association_name, association_type)
|
|
53
72
|
if association_type == :has_many
|
|
54
73
|
parent.association(association_name).loaded!
|
|
@@ -58,18 +77,21 @@ module JsonapiCompliable
|
|
|
58
77
|
end
|
|
59
78
|
end
|
|
60
79
|
|
|
80
|
+
# (see Adapters::Abstract#create)
|
|
61
81
|
def create(model_class, create_params)
|
|
62
82
|
instance = model_class.new(create_params)
|
|
63
83
|
instance.save
|
|
64
84
|
instance
|
|
65
85
|
end
|
|
66
86
|
|
|
87
|
+
# (see Adapters::Abstract#update)
|
|
67
88
|
def update(model_class, update_params)
|
|
68
89
|
instance = model_class.find(update_params.delete(:id))
|
|
69
90
|
instance.update_attributes(update_params)
|
|
70
91
|
instance
|
|
71
92
|
end
|
|
72
93
|
|
|
94
|
+
# (see Adapters::Abstract#destroy)
|
|
73
95
|
def destroy(model_class, id)
|
|
74
96
|
instance = model_class.find(id)
|
|
75
97
|
instance.destroy
|