Skip to content

Commit 4e46ed0

Browse files
committed
Merge pull request #258 from cerebris/links
Links
2 parents d45d64b + 1c1c1c9 commit 4e46ed0

15 files changed

Lines changed: 731 additions & 34 deletions

README.md

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -534,23 +534,22 @@ Callbacks can also be defined for `JSONAPI::OperationsProcessor` events:
534534
- `:remove_has_many_association_operation`: A `remove_has_many_association_operation`.
535535
- `:remove_has_one_association_operation`: A `remove_has_one_association_operation`.
536536

537-
The operation callbacks have access to two meta data hashes, `@operations_meta` and `@operation_meta`, the full list of
538-
`@operations`, each individual `@operation` and the `@result` variables.
537+
The operation callbacks have access to two meta data hashes, `@operations_meta` and `@operation_meta`, two links hashes,
538+
`@operations_links` and `@operation_links`, the full list of `@operations`, each individual `@operation` and the
539+
`@result` variables.
539540

540541
##### Custom `OperationsProcessor` Example to Return total_count in Meta
541542

543+
Note: this can also be accomplished with the `top_level_meta_include_record_count` option, and in most cases that will
544+
be the better option.
545+
542546
To return the total record count of a find operation in the meta data of a find operation you can create a custom
543547
OperationsProcessor. For example:
544548

545549
```ruby
546550
class CountingActiveRecordOperationsProcessor < ActiveRecordOperationsProcessor
547551
after_find_operation do
548-
count = @operation.resource_klass.find_count(@operation.resource_klass.verify_filters(@operation.filters, @context),
549-
context: @context,
550-
include_directives: @operation.include_directives,
551-
sort_criteria: @operation.sort_criteria)
552-
553-
@operation_meta[:total_records] = count
552+
@operation_meta[:total_records] = @operation.record_count
554553
end
555554
end
556555
```
@@ -1179,6 +1178,42 @@ end
11791178

11801179
You would specify this in `JSONAPI.configure` as `:upper_camelized`.
11811180

1181+
## Configuration
1182+
1183+
JR has a few configuration options. Some have already been mentioned above. To set configuration options create an
1184+
initializer and add the options you wish to set. All options have defaults, so you only need to set the options that
1185+
are different. The default options are shown below.
1186+
1187+
```ruby
1188+
JSONAPI.configure do |config|
1189+
#:underscored_key, :camelized_key, :dasherized_key, or custom
1190+
config.json_key_format = :dasherized_key
1191+
1192+
#:underscored_route, :camelized_route, :dasherized_route, or custom
1193+
config.route_format = :dasherized_route
1194+
1195+
#:basic, :active_record, or custom
1196+
config.operations_processor = :active_record
1197+
1198+
config.allowed_request_params = [:include, :fields, :format, :controller, :action, :sort, :page]
1199+
1200+
# :none, :offset, :paged, or a custom paginator name
1201+
config.default_paginator = :none
1202+
1203+
# Output pagination links at top level
1204+
config.top_level_links_include_pagination = true
1205+
1206+
config.default_page_size = 10
1207+
config.maximum_page_size = 20
1208+
1209+
# Output the record count in top level meta data for find operations
1210+
config.top_level_meta_include_record_count = false
1211+
config.top_level_meta_record_count_key = :record_count
1212+
1213+
config.use_text_errors = false
1214+
end
1215+
```
1216+
11821217
## Contributing
11831218

11841219
1. Fork it ( http://github.com/cerebris/jsonapi-resources/fork )

lib/jsonapi/acts_as_resource_controller.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ def base_response_meta
123123
{}
124124
end
125125

126+
def base_response_links
127+
{}
128+
end
129+
126130
def render_errors(errors)
127131
operation_results = JSONAPI::OperationResults.new()
128132
result = JSONAPI::ErrorsOperationResult.new(errors[0].status, errors)
@@ -147,7 +151,9 @@ def create_response_document(operation_results)
147151
key_formatter: key_formatter,
148152
route_formatter: route_formatter,
149153
base_meta: base_response_meta,
150-
resource_serializer_klass: resource_serializer_klass
154+
base_links: base_response_links,
155+
resource_serializer_klass: resource_serializer_klass,
156+
request: @request
151157
}
152158
)
153159
end

lib/jsonapi/configuration.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ class Configuration
1313
:default_paginator,
1414
:default_page_size,
1515
:maximum_page_size,
16-
:use_text_errors
16+
:use_text_errors,
17+
:top_level_links_include_pagination,
18+
:top_level_meta_include_record_count,
19+
:top_level_meta_record_count_key
1720

1821
def initialize
1922
#:underscored_key, :camelized_key, :dasherized_key, or custom
@@ -30,8 +33,17 @@ def initialize
3033
# :none, :offset, :paged, or a custom paginator name
3134
self.default_paginator = :none
3235

36+
# Output pagination links at top level
37+
self.top_level_links_include_pagination = true
38+
3339
self.default_page_size = 10
3440
self.maximum_page_size = 20
41+
42+
# Metadata
43+
# Output record count in top level meta for find operation
44+
self.top_level_meta_include_record_count = false
45+
self.top_level_meta_record_count_key = :record_count
46+
3547
self.use_text_errors = false
3648
end
3749

@@ -69,6 +81,18 @@ def maximum_page_size=(maximum_page_size)
6981
def use_text_errors=(use_text_errors)
7082
@use_text_errors = use_text_errors
7183
end
84+
85+
def top_level_links_include_pagination=(top_level_links_include_pagination)
86+
@top_level_links_include_pagination = top_level_links_include_pagination
87+
end
88+
89+
def top_level_meta_include_record_count=(top_level_meta_include_record_count)
90+
@top_level_meta_include_record_count = top_level_meta_include_record_count
91+
end
92+
93+
def top_level_meta_record_count_key=(top_level_meta_record_count_key)
94+
@top_level_meta_record_count_key = top_level_meta_record_count_key
95+
end
7296
end
7397

7498
class << self

lib/jsonapi/operation.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,41 @@ def initialize(resource_klass, options = {})
2323
super(resource_klass, false)
2424
end
2525

26+
def record_count
27+
@_record_count ||= @resource_klass.find_count(@resource_klass.verify_filters(@filters, @context),
28+
context: @context,
29+
include_directives: @include_directives)
30+
end
31+
32+
def pagination_params
33+
if @paginator && JSONAPI.configuration.top_level_links_include_pagination
34+
options = {}
35+
options[:record_count] = record_count if @paginator.class.requires_record_count
36+
return @paginator.links_page_params(options)
37+
else
38+
return {}
39+
end
40+
end
41+
2642
def apply(context)
2743
resource_records = @resource_klass.find(@resource_klass.verify_filters(@filters, context),
2844
context: context,
2945
include_directives: @include_directives,
3046
sort_criteria: @sort_criteria,
3147
paginator: @paginator)
3248

33-
return JSONAPI::ResourcesOperationResult.new(:ok, resource_records)
49+
options = {}
50+
if JSONAPI.configuration.top_level_links_include_pagination
51+
options[:pagination_params] = pagination_params
52+
end
53+
54+
if JSONAPI.configuration.top_level_meta_include_record_count
55+
options[:record_count] = record_count
56+
end
57+
58+
return JSONAPI::ResourcesOperationResult.new(:ok,
59+
resource_records,
60+
options)
3461

3562
rescue JSONAPI::Exceptions::Error => e
3663
return JSONAPI::ErrorsOperationResult.new(e.errors[0].code, e.errors)

lib/jsonapi/operation_result.rb

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,53 @@ module JSONAPI
22
class OperationResult
33
attr_accessor :code
44
attr_accessor :meta
5+
attr_accessor :links
6+
attr_accessor :options
57

6-
def initialize(code)
8+
def initialize(code, options = {})
79
@code = code
8-
@meta = {}
10+
@options = options
11+
@meta = options.fetch(:meta, {})
12+
@links = options.fetch(:links, {})
913
end
1014
end
1115

1216
class ErrorsOperationResult < OperationResult
1317
attr_accessor :errors
1418

15-
def initialize(code, errors)
19+
def initialize(code, errors, options = {})
1620
@errors = errors
17-
super(code)
21+
super(code, options)
1822
end
1923
end
2024

2125
class ResourceOperationResult < OperationResult
2226
attr_accessor :resource
2327

24-
def initialize(code, resource)
28+
def initialize(code, resource, options = {})
2529
@resource = resource
26-
super(code)
30+
super(code, options)
2731
end
2832
end
2933

3034
class ResourcesOperationResult < OperationResult
31-
attr_accessor :resources
35+
attr_accessor :resources, :pagination_params, :record_count
3236

33-
def initialize(code, resources)
37+
def initialize(code, resources, options = {})
3438
@resources = resources
35-
super(code)
39+
@pagination_params = options.fetch(:pagination_params, {})
40+
@record_count = options[:record_count]
41+
super(code, options)
3642
end
3743
end
3844

3945
class LinksObjectOperationResult < OperationResult
4046
attr_accessor :parent_resource, :association
4147

42-
def initialize(code, parent_resource, association)
48+
def initialize(code, parent_resource, association, options = {})
4349
@parent_resource = parent_resource
4450
@association = association
45-
super(code)
51+
super(code, options)
4652
end
4753
end
4854
end

lib/jsonapi/operation_results.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ module JSONAPI
22
class OperationResults
33
attr_accessor :results
44
attr_accessor :meta
5+
attr_accessor :links
56

67
def initialize
78
@results = []
89
@has_errors = false
910
@meta = {}
11+
@links = {}
1012
end
1113

1214
def add_result(result)

lib/jsonapi/operations_processor.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,29 @@ def process(request)
4141

4242
run_callbacks :operations do
4343
transaction do
44+
# Links and meta data global to the set of operations
4445
@operations_meta = {}
46+
@operations_links = {}
4547
@operations.each do |operation|
4648
@operation = operation
49+
# Links and meta data for each operation
4750
@operation_meta = {}
51+
@operation_links = {}
4852
run_callbacks :operation do
4953
@result = nil
5054
run_callbacks @operation.class.name.demodulize.underscore.to_sym do
5155
@result = process_operation(@operation)
5256
end
5357
@result.meta.merge!(@operation_meta)
58+
@result.links.merge!(@operation_links)
5459
@results.add_result(@result)
5560
if @results.has_errors?
5661
rollback
5762
end
5863
end
5964
end
6065
@results.meta = @operations_meta
66+
@results.links = @operations_links
6167
end
6268
end
6369
@results

0 commit comments

Comments
 (0)