jsonapi_compliable 0.3.8 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jsonapi_compliable/base.rb +9 -6
- data/lib/jsonapi_compliable/dsl.rb +15 -0
- data/lib/jsonapi_compliable/errors.rb +21 -0
- data/lib/jsonapi_compliable/stats/dsl.rb +54 -0
- data/lib/jsonapi_compliable/stats/payload.rb +34 -0
- data/lib/jsonapi_compliable/util/pagination.rb +11 -0
- data/lib/jsonapi_compliable/util/scoping.rb +2 -2
- data/lib/jsonapi_compliable/version.rb +1 -1
- data/lib/jsonapi_compliable.rb +3 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0418e83aaae7d67b616dab559f7f5986430d022
|
4
|
+
data.tar.gz: da31edddd52610cd95b14868b797b4197b508a68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf21cdf1b18b9af6190d790214e24009ab48c679d18f4d12b40d97952053d0752e1363d59dc8921a77cf3b845de07327381e412fa600bebaaa1193d3b7fe40de
|
7
|
+
data.tar.gz: 999ba235c7156753d37c5f8a3a8a70dc5f980fde4598e37d4ca6c597cc92db8ce04dac4bc6a88daba63c789a9512083587e80da87e5bec3c60b57c88e8d76efc
|
@@ -7,7 +7,7 @@ module JsonapiCompliable
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
class_attribute :_jsonapi_compliable
|
10
|
-
attr_reader :
|
10
|
+
attr_reader :_jsonapi_scope
|
11
11
|
|
12
12
|
before_action :parse_fieldsets!
|
13
13
|
after_action :reset_scope_flag
|
@@ -36,13 +36,14 @@ module JsonapiCompliable
|
|
36
36
|
scope = JsonapiCompliable::Scope::ExtraFields.new(self, scope).apply if extra_fields
|
37
37
|
scope = JsonapiCompliable::Scope::Sideload.new(self, scope).apply if includes
|
38
38
|
scope = JsonapiCompliable::Scope::Sort.new(self, scope).apply if sort
|
39
|
+
# This is set before pagination so it can be re-used for stats
|
40
|
+
@_jsonapi_scope = scope
|
39
41
|
scope = JsonapiCompliable::Scope::Paginate.new(self, scope).apply if paginate
|
40
|
-
@_jsonapi_scoped = true
|
41
42
|
scope
|
42
43
|
end
|
43
44
|
|
44
45
|
def reset_scope_flag
|
45
|
-
@
|
46
|
+
@_jsonapi_scope = nil
|
46
47
|
end
|
47
48
|
|
48
49
|
def parse_fieldsets!
|
@@ -51,14 +52,16 @@ module JsonapiCompliable
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def render_ams(scope, opts = {})
|
54
|
-
|
55
|
+
scoped = Util::Scoping.apply?(self, scope, opts.delete(:scope)) ? jsonapi_scope(scope) : scope
|
55
56
|
options = default_ams_options
|
56
57
|
options[:include] = forced_includes || Util::IncludeParams.scrub(self)
|
57
|
-
options[:jsonapi] =
|
58
|
+
options[:jsonapi] = JsonapiCompliable::Util::Pagination.zero?(params) ? [] : scoped
|
58
59
|
options[:fields] = Util::FieldParams.fieldset(params, :fields) if params[:fields]
|
59
60
|
options[:extra_fields] = Util::FieldParams.fieldset(params, :extra_fields) if params[:extra_fields]
|
60
|
-
|
61
|
+
options[:meta] ||= {}
|
61
62
|
options.merge!(opts)
|
63
|
+
options[:meta][:stats] = Stats::Payload.new(self, scoped).generate if params[:stats]
|
64
|
+
|
62
65
|
render(options)
|
63
66
|
end
|
64
67
|
|
@@ -5,6 +5,7 @@ module JsonapiCompliable
|
|
5
5
|
:extra_fields,
|
6
6
|
:filters,
|
7
7
|
:sorting,
|
8
|
+
:stats,
|
8
9
|
:pagination
|
9
10
|
|
10
11
|
def initialize
|
@@ -19,6 +20,7 @@ module JsonapiCompliable
|
|
19
20
|
instance.extra_fields = extra_fields.deep_dup
|
20
21
|
instance.sorting = sorting.deep_dup
|
21
22
|
instance.pagination = pagination.deep_dup
|
23
|
+
instance.stats = stats.deep_dup
|
22
24
|
instance
|
23
25
|
end
|
24
26
|
|
@@ -27,6 +29,7 @@ module JsonapiCompliable
|
|
27
29
|
@filters = {}
|
28
30
|
@default_filters = {}
|
29
31
|
@extra_fields = {}
|
32
|
+
@stats = {}
|
30
33
|
@sorting = nil
|
31
34
|
@pagination = nil
|
32
35
|
end
|
@@ -50,6 +53,12 @@ module JsonapiCompliable
|
|
50
53
|
}
|
51
54
|
end
|
52
55
|
|
56
|
+
def allow_stat(symbol_or_hash, &blk)
|
57
|
+
dsl = Stats::DSL.new(symbol_or_hash)
|
58
|
+
dsl.instance_eval(&blk) if blk
|
59
|
+
@stats[dsl.name] = dsl
|
60
|
+
end
|
61
|
+
|
53
62
|
def default_filter(name, &blk)
|
54
63
|
@default_filters[name.to_sym] = {
|
55
64
|
filter: blk
|
@@ -71,5 +80,11 @@ module JsonapiCompliable
|
|
71
80
|
proc: blk
|
72
81
|
}
|
73
82
|
end
|
83
|
+
|
84
|
+
def stat(attribute, calculation)
|
85
|
+
stats_dsl = @stats[attribute] || @stats[attribute.to_sym]
|
86
|
+
raise Errors::StatNotFound.new(attribute, calculation) unless stats_dsl
|
87
|
+
stats_dsl.calculation(calculation)
|
88
|
+
end
|
74
89
|
end
|
75
90
|
end
|
@@ -11,5 +11,26 @@ module JsonapiCompliable
|
|
11
11
|
"Requested page size #{@size} is greater than max supported size #{@max}"
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
class StatNotFound < StandardError
|
16
|
+
def initialize(attribute, calculation)
|
17
|
+
@attribute = attribute
|
18
|
+
@calculation = calculation
|
19
|
+
end
|
20
|
+
|
21
|
+
def message
|
22
|
+
"No stat configured for calculation #{pretty(@calculation)} on attribute #{pretty(@attribute)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def pretty(input)
|
28
|
+
if input.is_a?(Symbol)
|
29
|
+
":#{input}"
|
30
|
+
else
|
31
|
+
"'#{input}'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
14
35
|
end
|
15
36
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module JsonapiCompliable
|
2
|
+
module Stats
|
3
|
+
class DSL
|
4
|
+
attr_reader :name, :calculations
|
5
|
+
|
6
|
+
def self.defaults
|
7
|
+
{
|
8
|
+
count: ->(scope, attr) { scope.count },
|
9
|
+
average: ->(scope, attr) { scope.average(attr).to_f },
|
10
|
+
sum: ->(scope, attr) { scope.sum(attr) },
|
11
|
+
maximum: ->(scope, attr) { scope.maximum(attr) },
|
12
|
+
minimum: ->(scope, attr) { scope.minimum(attr) }
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(config)
|
17
|
+
config = { config => [] } if config.is_a?(Symbol)
|
18
|
+
|
19
|
+
@calculations = {}
|
20
|
+
@name = config.keys.first
|
21
|
+
Array(config.values.first).each { |c| send(:"#{c}!") }
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(meth, *args, &blk)
|
25
|
+
@calculations[meth] = blk
|
26
|
+
end
|
27
|
+
|
28
|
+
def calculation(name)
|
29
|
+
callable = @calculations[name] || @calculations[name.to_sym]
|
30
|
+
callable || raise(Errors::StatNotFound.new(@name, name))
|
31
|
+
end
|
32
|
+
|
33
|
+
def count!
|
34
|
+
@calculations[:count] = self.class.defaults[:count]
|
35
|
+
end
|
36
|
+
|
37
|
+
def sum!
|
38
|
+
@calculations[:sum] = self.class.defaults[:sum]
|
39
|
+
end
|
40
|
+
|
41
|
+
def average!
|
42
|
+
@calculations[:average] = self.class.defaults[:average]
|
43
|
+
end
|
44
|
+
|
45
|
+
def maximum!
|
46
|
+
@calculations[:maximum] = self.class.defaults[:maximum]
|
47
|
+
end
|
48
|
+
|
49
|
+
def minimum!
|
50
|
+
@calculations[:minimum] = self.class.defaults[:minimum]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module JsonapiCompliable
|
2
|
+
module Stats
|
3
|
+
class Payload
|
4
|
+
def initialize(controller, scope)
|
5
|
+
@dsl = controller._jsonapi_compliable
|
6
|
+
@directive = controller.params[:stats]
|
7
|
+
@scope = controller._jsonapi_scope || scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate
|
11
|
+
{}.tap do |stats|
|
12
|
+
@directive.each_pair do |name, calculation|
|
13
|
+
stats[name] = {}
|
14
|
+
|
15
|
+
each_calculation(name, calculation) do |calc, function|
|
16
|
+
stats[name][calc] = function.call(@scope, name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def each_calculation(name, calculation_string)
|
25
|
+
calculations = calculation_string.split(',').map(&:to_sym)
|
26
|
+
|
27
|
+
calculations.each do |calc|
|
28
|
+
function = @dsl.stat(name, calc)
|
29
|
+
yield calc, function
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -3,9 +3,9 @@ module JsonapiCompliable
|
|
3
3
|
class Scoping
|
4
4
|
def self.apply?(controller, object, force)
|
5
5
|
return false if force == false
|
6
|
-
return true if
|
6
|
+
return true if controller._jsonapi_scope.nil? && object.is_a?(ActiveRecord::Relation)
|
7
7
|
|
8
|
-
already_scoped = !!controller.
|
8
|
+
already_scoped = !!controller._jsonapi_scope
|
9
9
|
is_activerecord = object.is_a?(ActiveRecord::Base)
|
10
10
|
is_activerecord_array = object.is_a?(Array) && object[0].is_a?(ActiveRecord::Base)
|
11
11
|
|
data/lib/jsonapi_compliable.rb
CHANGED
@@ -13,9 +13,12 @@ require "jsonapi_compliable/scope/extra_fields"
|
|
13
13
|
require "jsonapi_compliable/scope/filterable"
|
14
14
|
require "jsonapi_compliable/scope/default_filter"
|
15
15
|
require "jsonapi_compliable/scope/filter"
|
16
|
+
require "jsonapi_compliable/stats/dsl"
|
17
|
+
require "jsonapi_compliable/stats/payload"
|
16
18
|
require "jsonapi_compliable/util/include_params"
|
17
19
|
require "jsonapi_compliable/util/field_params"
|
18
20
|
require "jsonapi_compliable/util/scoping"
|
21
|
+
require "jsonapi_compliable/util/pagination"
|
19
22
|
|
20
23
|
require 'jsonapi_compliable/railtie' if defined?(::Rails)
|
21
24
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonapi_compliable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Richmond
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-11-
|
12
|
+
date: 2016-11-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -228,8 +228,11 @@ files:
|
|
228
228
|
- lib/jsonapi_compliable/scope/paginate.rb
|
229
229
|
- lib/jsonapi_compliable/scope/sideload.rb
|
230
230
|
- lib/jsonapi_compliable/scope/sort.rb
|
231
|
+
- lib/jsonapi_compliable/stats/dsl.rb
|
232
|
+
- lib/jsonapi_compliable/stats/payload.rb
|
231
233
|
- lib/jsonapi_compliable/util/field_params.rb
|
232
234
|
- lib/jsonapi_compliable/util/include_params.rb
|
235
|
+
- lib/jsonapi_compliable/util/pagination.rb
|
233
236
|
- lib/jsonapi_compliable/util/scoping.rb
|
234
237
|
- lib/jsonapi_compliable/version.rb
|
235
238
|
homepage:
|