caprese 0.3.19.3 → 0.3.20
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/CHANGELOG.md +6 -0
- data/lib/caprese/adapter/json_api.rb +2 -1
- data/lib/caprese/controller/concerns/aliasing.rb +65 -0
- data/lib/caprese/controller/concerns/persistence.rb +10 -2
- data/lib/caprese/controller/concerns/query.rb +4 -4
- data/lib/caprese/controller/concerns/relationships.rb +8 -6
- data/lib/caprese/controller/concerns/typing.rb +9 -1
- data/lib/caprese/controller.rb +4 -0
- data/lib/caprese/record/aliasing.rb +59 -0
- data/lib/caprese/record/errors.rb +1 -1
- data/lib/caprese/record.rb +2 -2
- data/lib/caprese/serializer/concerns/aliasing.rb +17 -0
- data/lib/caprese/serializer/concerns/links.rb +2 -0
- data/lib/caprese/serializer.rb +3 -1
- data/lib/caprese/version.rb +1 -1
- metadata +5 -3
- data/lib/caprese/record/attribute_aliasing.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f20459249bd9aa768296fff0603eacaec3d53c99
|
|
4
|
+
data.tar.gz: 667f7a0cd853d8f69099a78ecfaa76c48d15f5de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17f2e85ce1abeddd71ee15ce76c68e425b7f6cc8a4e2f71732cdebcd37df424dd8927716a6927cdb05ed861bd09cc3b1fdddb0ad8f8f39ba18b7cf1b905e6a17
|
|
7
|
+
data.tar.gz: f936557de63859192d37419ba50df905949835df4359e0ccfde5ea058b7093f4a7b4f538a5e76496accc17e8dfc55ff1f169a56950685fe47bddb7254cd76b79
|
data/CHANGELOG.md
CHANGED
|
@@ -111,3 +111,9 @@
|
|
|
111
111
|
## 0.3.19.3
|
|
112
112
|
|
|
113
113
|
* Fix use of `ActiveRecord::Validations::AssociatedValidator` in `Caprese::AssociatedValidator`
|
|
114
|
+
|
|
115
|
+
## 0.3.20
|
|
116
|
+
|
|
117
|
+
* Add `Caprese::Controller#resource_type_aliases` method that returns object mapping type aliases to actual types for the application
|
|
118
|
+
* Add `Caprese::Record.caprese_field_aliases` method that returns object mapping field aliases to actual fields for the record
|
|
119
|
+
* Add `Caprese::Record.caprese_type` method that returns singular symbol indicating the type to use when serializing the record. (`Caprese::Serializer.json_api_key` now uses this.)
|
|
@@ -425,7 +425,8 @@ module Caprese
|
|
|
425
425
|
allow_wildcard: true
|
|
426
426
|
)
|
|
427
427
|
serializer.associations(include_directive).each_with_object({}) do |association, hash|
|
|
428
|
-
|
|
428
|
+
aliased_key = serializer.object.class.caprese_alias_field(association.key)
|
|
429
|
+
hash[aliased_key] = Relationship.new(
|
|
429
430
|
serializer,
|
|
430
431
|
instance_options,
|
|
431
432
|
association,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
require 'caprese/errors'
|
|
3
|
+
|
|
4
|
+
module Caprese
|
|
5
|
+
module Aliasing
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
# Specifies specific resource models that have types that are aliased.
|
|
9
|
+
# @note The `caprese_type` class variable of the model should also be set to the new type
|
|
10
|
+
# @example
|
|
11
|
+
# {
|
|
12
|
+
# questions: attributes
|
|
13
|
+
# }
|
|
14
|
+
def resource_type_aliases
|
|
15
|
+
{}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Checks resource_type_aliases for a type alias, or returns the type already stated
|
|
19
|
+
#
|
|
20
|
+
# @param [Symbol] type the type to search for an alias for
|
|
21
|
+
# @return [Symbol] the actual type for the type alias
|
|
22
|
+
def actual_type(type)
|
|
23
|
+
resource_type_aliases[type] || type
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Gets the actual field name for the controller_record_class for any given field requested
|
|
27
|
+
#
|
|
28
|
+
# @param [Symbol,String] field the field that was requested
|
|
29
|
+
# @param [Class] klass the klass to get field aliases for
|
|
30
|
+
# @return [Symbol] the actual field name for the field requested
|
|
31
|
+
def actual_field(field, klass = controller_record_class)
|
|
32
|
+
klass.caprese_unalias_field(field.to_sym)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Takes in a set of possibly aliased includes and converts them to their actual names
|
|
36
|
+
#
|
|
37
|
+
# @param [String] the CSV string of possibly aliased includes
|
|
38
|
+
# @return [Array<String>] the actual includes
|
|
39
|
+
def actual_includes(includes)
|
|
40
|
+
includes.split(',').map do |i|
|
|
41
|
+
if(i = i.split('.')).size > 1
|
|
42
|
+
klass = nil
|
|
43
|
+
i.map do |i2|
|
|
44
|
+
actual = actual_field(i2, klass)
|
|
45
|
+
klass = klass.reflections[actual].klass
|
|
46
|
+
actual
|
|
47
|
+
end.join('.')
|
|
48
|
+
else
|
|
49
|
+
actual_field(i)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Takes in a set of possibly aliased fields with types and converts them to their actual
|
|
55
|
+
# types and fields
|
|
56
|
+
#
|
|
57
|
+
# @param [Hash<Array>] the hash of possibly aliased resource types with their possibly aliased field specifier arrays
|
|
58
|
+
# @return [Hash<Array>] the actual resource type and fields
|
|
59
|
+
def actual_fields(fields)
|
|
60
|
+
Hash[*fields.each do |type, fields|
|
|
61
|
+
[actual_type(type), fields.map { |f| actual_field(f, record_class(type)) }]
|
|
62
|
+
end]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -220,12 +220,20 @@ module Caprese
|
|
|
220
220
|
# @param [Array] permitted_params the permitted params for the action
|
|
221
221
|
# @param [Parameters] data the data sent to the server to construct and assign to the record
|
|
222
222
|
def assign_record_attributes(record, permitted_params, data)
|
|
223
|
-
attributes = data[:attributes].try(:permit, *permitted_params)
|
|
223
|
+
attributes = data[:attributes].try(:permit, *permitted_params).try(:inject, {}) do |out, (attr, val)|
|
|
224
|
+
out[actual_field(attr, record.class)] = val
|
|
225
|
+
out
|
|
226
|
+
end || {}
|
|
224
227
|
|
|
225
228
|
data[:relationships]
|
|
226
229
|
.try(:slice, *flattened_keys_for(permitted_params))
|
|
227
230
|
.try(:each) do |relationship_name, relationship_data|
|
|
228
|
-
|
|
231
|
+
actual_relationship_name = actual_field(relationship_name, record.class)
|
|
232
|
+
|
|
233
|
+
# TODO: Add checkme for relationship_name to ensure that format is correct (not Array when actually Record, vice versa)
|
|
234
|
+
# No relationship exists as well
|
|
235
|
+
|
|
236
|
+
attributes[actual_relationship_name] = records_for_relationship(
|
|
229
237
|
record,
|
|
230
238
|
nested_params_for(relationship_name, permitted_params),
|
|
231
239
|
relationship_name,
|
|
@@ -134,9 +134,9 @@ module Caprese
|
|
|
134
134
|
query_params[:sort].each do |sort_field|
|
|
135
135
|
ordering = ordering.merge(
|
|
136
136
|
if sort_field[0] == '-' # EX: -created_at, sort by created_at descending
|
|
137
|
-
{ sort_field[1..-1] => :desc }
|
|
137
|
+
{ actual_field(sort_field[1..-1]) => :desc }
|
|
138
138
|
else
|
|
139
|
-
{ sort_field => :asc }
|
|
139
|
+
{ actual_field(sort_field) => :asc }
|
|
140
140
|
end
|
|
141
141
|
)
|
|
142
142
|
end
|
|
@@ -172,9 +172,9 @@ module Caprese
|
|
|
172
172
|
scope = record_scope(unversion(params[:controller]).to_sym)
|
|
173
173
|
|
|
174
174
|
if scope.any? && query_params[:filter].try(:any?)
|
|
175
|
-
if (valid_filters = query_params[:filter].select { |k, _| scope.column_names.include? k }).present?
|
|
175
|
+
if (valid_filters = query_params[:filter].select { |k, _| scope.column_names.include? actual_field(k).to_s }).present?
|
|
176
176
|
valid_filters.each do |k, v|
|
|
177
|
-
scope = scope.where(k => v)
|
|
177
|
+
scope = scope.where(actual_field(k) => v)
|
|
178
178
|
end
|
|
179
179
|
end
|
|
180
180
|
end
|
|
@@ -207,24 +207,26 @@ module Caprese
|
|
|
207
207
|
)
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
+
relationship_name = queried_association.reflection.name
|
|
211
|
+
|
|
210
212
|
successful =
|
|
211
213
|
case queried_association.reflection.macro
|
|
212
214
|
when :has_many
|
|
213
215
|
if request.patch?
|
|
214
|
-
queried_record.send("#{
|
|
216
|
+
queried_record.send("#{relationship_name}=", relationship_resources)
|
|
215
217
|
elsif request.post?
|
|
216
|
-
queried_record.send(
|
|
218
|
+
queried_record.send(relationship_name).push relationship_resources
|
|
217
219
|
elsif request.delete?
|
|
218
|
-
queried_record.send(
|
|
220
|
+
queried_record.send(relationship_name).delete relationship_resources
|
|
219
221
|
end
|
|
220
222
|
when :has_one
|
|
221
223
|
if request.patch?
|
|
222
|
-
queried_record.send("#{
|
|
224
|
+
queried_record.send("#{relationship_name}=", relationship_resources[0])
|
|
223
225
|
objects[0].save
|
|
224
226
|
end
|
|
225
227
|
when :belongs_to
|
|
226
228
|
if request.patch?
|
|
227
|
-
queried_record.send("#{
|
|
229
|
+
queried_record.send("#{relationship_name}=", relationship_resources[0])
|
|
228
230
|
queried_record.save
|
|
229
231
|
end
|
|
230
232
|
end
|
|
@@ -247,7 +249,7 @@ module Caprese
|
|
|
247
249
|
def queried_association
|
|
248
250
|
unless @queried_association
|
|
249
251
|
begin
|
|
250
|
-
@queried_association = queried_record.association(params[:relationship])
|
|
252
|
+
@queried_association = queried_record.association(actual_field(params[:relationship]))
|
|
251
253
|
rescue ActiveRecord::AssociationNotFoundError => e
|
|
252
254
|
fail AssociationNotFoundError.new(params[:relationship])
|
|
253
255
|
end
|
|
@@ -16,7 +16,15 @@ module Caprese
|
|
|
16
16
|
# @param [Symbol] type the record type to get the class for
|
|
17
17
|
# @return [Class] the class for a given record type
|
|
18
18
|
def record_class(type)
|
|
19
|
-
|
|
19
|
+
begin
|
|
20
|
+
type.to_s.classify.constantize
|
|
21
|
+
rescue NameError => e
|
|
22
|
+
if resource_type_aliases[type.to_sym]
|
|
23
|
+
record_class(resource_type_aliases[type.to_sym].to_sym)
|
|
24
|
+
else
|
|
25
|
+
raise e
|
|
26
|
+
end
|
|
27
|
+
end
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
# Gets the record class for the current controller
|
data/lib/caprese/controller.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'action_controller'
|
|
2
2
|
require 'active_support/configurable'
|
|
3
3
|
require 'caprese/concerns/versioning'
|
|
4
|
+
require 'caprese/controller/concerns/aliasing'
|
|
4
5
|
require 'caprese/controller/concerns/callbacks'
|
|
5
6
|
require 'caprese/controller/concerns/errors'
|
|
6
7
|
require 'caprese/controller/concerns/persistence'
|
|
@@ -13,7 +14,10 @@ module Caprese
|
|
|
13
14
|
# TODO: Convert to ActionController::API with Rails 5
|
|
14
15
|
class Controller < ActionController::Base
|
|
15
16
|
include ActiveSupport::Configurable
|
|
17
|
+
include Aliasing
|
|
16
18
|
include Callbacks
|
|
19
|
+
# FIXME: Be careful about including `Errors` in certain order, because it has `rescue_from Exception` and this affects
|
|
20
|
+
# control flow with other rescue handlers if included after their modules
|
|
17
21
|
include Errors
|
|
18
22
|
include Persistence
|
|
19
23
|
include Query
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Caprese
|
|
4
|
+
module Record
|
|
5
|
+
module Aliasing
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
# Provides an intermediary helper method on records that defines non-column attributes for records
|
|
9
|
+
# @note This exists so there is a method by which to state that a non-column attribute should
|
|
10
|
+
# have an error source pointer like `/data/attributes/[name]` instead of `/data/relationships/[name]`
|
|
11
|
+
def caprese_is_attribute?(attribute_name)
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Checks that any field provided is either an attribute on the record, or an aliased field, or none
|
|
16
|
+
#
|
|
17
|
+
# @param [String,Symbol] field the field to check for on this record
|
|
18
|
+
# @return [Boolean] whether or not the field is on the record
|
|
19
|
+
def caprese_is_field?(field)
|
|
20
|
+
respond_to?(field = field.to_sym) || caprese_is_attribute?(field) || self.class.caprese_field_aliases[field]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
# Given an actual field, convert to its appropriate field alias for the class
|
|
25
|
+
# @note The reason this is useful is because ActiveRecord validations must validate the actual field name of a
|
|
26
|
+
# model, but when we add errors they should always have aliased fields
|
|
27
|
+
#
|
|
28
|
+
# @param [String,Symbol] field the actual field name to alias
|
|
29
|
+
# @return [Symbol] the aliased field name, or the original name symbolized
|
|
30
|
+
def caprese_alias_field(field)
|
|
31
|
+
caprese_field_aliases.invert[field = field.to_sym] || field
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Given an aliased field, convert to its actual field for the class
|
|
35
|
+
#
|
|
36
|
+
# @param [String,Symbol] field the actual field name to alias
|
|
37
|
+
# @return [Symbol] the aliased field name, or the original name symbolized
|
|
38
|
+
def caprese_unalias_field(field)
|
|
39
|
+
caprese_field_aliases[field = field.to_sym] || field
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Provides the ability to display an aliased field name to the consumer of the API, and then map that name
|
|
43
|
+
# to its real name on the server
|
|
44
|
+
# @example
|
|
45
|
+
# {
|
|
46
|
+
# alias: :actual
|
|
47
|
+
# }
|
|
48
|
+
def caprese_field_aliases
|
|
49
|
+
{}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The type that is serialized and responded with for this class
|
|
53
|
+
def caprese_type
|
|
54
|
+
self.name.underscore
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
data/lib/caprese/record.rb
CHANGED
|
@@ -3,13 +3,13 @@ require 'active_support/concern'
|
|
|
3
3
|
require 'active_support/dependencies'
|
|
4
4
|
require 'caprese/errors'
|
|
5
5
|
require 'caprese/record/associated_validator'
|
|
6
|
-
require 'caprese/record/
|
|
6
|
+
require 'caprese/record/aliasing'
|
|
7
7
|
require 'caprese/record/errors'
|
|
8
8
|
|
|
9
9
|
module Caprese
|
|
10
10
|
module Record
|
|
11
11
|
extend ActiveSupport::Concern
|
|
12
|
-
include
|
|
12
|
+
include Aliasing
|
|
13
13
|
|
|
14
14
|
mattr_accessor :caprese_style_errors
|
|
15
15
|
@@caprese_style_errors = true
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Caprese
|
|
4
|
+
class Serializer < ActiveModel::Serializer
|
|
5
|
+
module Aliasing
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
# Override so we can get the values for serialization of aliased attributes just like unaliased
|
|
9
|
+
#
|
|
10
|
+
# @param [String,Symbol] attribute the attribute (aliased or not) to read for serialization
|
|
11
|
+
# @return [Value] the value of the attribute
|
|
12
|
+
def read_attribute_for_serialization(attribute)
|
|
13
|
+
super(self.object.class.caprese_unalias_field(attribute))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -80,6 +80,8 @@ module Caprese
|
|
|
80
80
|
def build_association_block(reflection_name)
|
|
81
81
|
primary_key = Caprese.config.resource_primary_key
|
|
82
82
|
|
|
83
|
+
reflection_name = reflection_name.to_sym
|
|
84
|
+
|
|
83
85
|
Proc.new do |serializer|
|
|
84
86
|
link :self do
|
|
85
87
|
url = "relationship_definition_#{serializer.version_name("#{object.class.name.underscore}_url")}"
|
data/lib/caprese/serializer.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'active_model_serializers'
|
|
2
2
|
require 'caprese/concerns/versioning'
|
|
3
|
+
require 'caprese/serializer/concerns/aliasing'
|
|
3
4
|
require 'caprese/serializer/concerns/links'
|
|
4
5
|
require 'caprese/serializer/concerns/lookup'
|
|
5
6
|
require 'caprese/serializer/concerns/relationships'
|
|
@@ -8,12 +9,13 @@ module Caprese
|
|
|
8
9
|
class Serializer < ActiveModel::Serializer
|
|
9
10
|
extend Versioning
|
|
10
11
|
include Versioning
|
|
12
|
+
include Aliasing
|
|
11
13
|
include Links
|
|
12
14
|
include Lookup
|
|
13
15
|
include Relationships
|
|
14
16
|
|
|
15
17
|
def json_key
|
|
16
|
-
|
|
18
|
+
object.class.caprese_type
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
data/lib/caprese/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: caprese
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.20
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Landgrebe
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: exe
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2017-04-
|
|
13
|
+
date: 2017-04-06 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: active_model_serializers
|
|
@@ -224,6 +224,7 @@ files:
|
|
|
224
224
|
- lib/caprese/adapter/json_api/resource_identifier.rb
|
|
225
225
|
- lib/caprese/concerns/versioning.rb
|
|
226
226
|
- lib/caprese/controller.rb
|
|
227
|
+
- lib/caprese/controller/concerns/aliasing.rb
|
|
227
228
|
- lib/caprese/controller/concerns/callbacks.rb
|
|
228
229
|
- lib/caprese/controller/concerns/errors.rb
|
|
229
230
|
- lib/caprese/controller/concerns/persistence.rb
|
|
@@ -234,11 +235,12 @@ files:
|
|
|
234
235
|
- lib/caprese/error.rb
|
|
235
236
|
- lib/caprese/errors.rb
|
|
236
237
|
- lib/caprese/record.rb
|
|
238
|
+
- lib/caprese/record/aliasing.rb
|
|
237
239
|
- lib/caprese/record/associated_validator.rb
|
|
238
|
-
- lib/caprese/record/attribute_aliasing.rb
|
|
239
240
|
- lib/caprese/record/errors.rb
|
|
240
241
|
- lib/caprese/routing/caprese_resources.rb
|
|
241
242
|
- lib/caprese/serializer.rb
|
|
243
|
+
- lib/caprese/serializer/concerns/aliasing.rb
|
|
242
244
|
- lib/caprese/serializer/concerns/links.rb
|
|
243
245
|
- lib/caprese/serializer/concerns/lookup.rb
|
|
244
246
|
- lib/caprese/serializer/concerns/relationships.rb
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
module Caprese
|
|
2
|
-
module Record
|
|
3
|
-
module AttributeAliasing
|
|
4
|
-
# Provides an intermediary helper method on records that defines non-column attributes for records
|
|
5
|
-
# @note This exists so there is a method by which to state that a non-column attribute should
|
|
6
|
-
# have an error source pointer like `/data/attributes/[name]` instead of `/data/relationships/[name]`
|
|
7
|
-
def caprese_is_attribute?(attribute_name)
|
|
8
|
-
false
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|