Skip to content

Commit a7296e8

Browse files
committed
Fix #1759, Grape integration, adds serialization_context
- improves improves serialization_context to take options and not depend on a `request` object. - adds descriptive error on missing serialization_context. - Document overriding `CollectionSerializer#paginated?`.
1 parent a52189c commit a7296e8

File tree

6 files changed

+63
-14
lines changed

6 files changed

+63
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Features:
99
- [#1426](https://github.com/rails-api/active_model_serializers/pull/1426) Add ActiveModelSerializers.config.default_includes (@empact)
1010

1111
Fixes:
12+
- [#1754](https://github.com/rails-api/active_model_serializers/pull/1754) Fixes #1759, Grape integration, improves serialization_context
13+
missing error message on pagination. Document overriding CollectionSerializer#paginated?. (@bf4)
1214
- [#1287](https://github.com/rails-api/active_model_serializers/pull/1287) Pass `fields` options from adapter to serializer. (@vasilakisfil)
1315
- [#1710](https://github.com/rails-api/active_model_serializers/pull/1710) Prevent association loading when `include_data` option
1416
is set to `false`. (@groyoh)

lib/active_model_serializers/adapter/json_api/pagination_links.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@ module ActiveModelSerializers
22
module Adapter
33
class JsonApi < Base
44
class PaginationLinks
5+
MissingSerializationContextError = Class.new(KeyError)
56
FIRST_PAGE = 1
67

78
attr_reader :collection, :context
89

910
def initialize(collection, adapter_options)
1011
@collection = collection
1112
@adapter_options = adapter_options
12-
@context = adapter_options.fetch(:serialization_context)
13+
@context = adapter_options.fetch(:serialization_context) do
14+
fail MissingSerializationContextError, <<-EOF.freeze
15+
JsonApi::PaginationLinks requires a ActiveModelSerializers::SerializationContext.
16+
Please pass a ':serialization_context' option or
17+
override CollectionSerializer#paginated? to return 'false'.
18+
EOF
19+
end
1320
end
1421

1522
def as_json

lib/active_model_serializers/serialization_context.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require 'active_support/core_ext/array/extract_options'
12
module ActiveModelSerializers
23
class SerializationContext
34
class << self
@@ -22,9 +23,15 @@ def default_url_options
2223

2324
attr_reader :request_url, :query_parameters, :key_transform
2425

25-
def initialize(request, options = {})
26-
@request_url = request.original_url[/\A[^?]+/]
27-
@query_parameters = request.query_parameters
26+
def initialize(*args)
27+
options = args.extract_options!
28+
if args.size == 1
29+
request = args.pop
30+
options[:request_url] = request.original_url[/\A[^?]+/]
31+
options[:query_parameters] = request.query_parameters
32+
end
33+
@request_url = options.delete(:request_url)
34+
@query_parameters = options.delete(:query_parameters)
2835
@url_helpers = options.delete(:url_helpers) || self.class.url_helpers
2936
@default_url_options = options.delete(:default_url_options) || self.class.default_url_options
3037
end

lib/grape/helpers/active_model_serializers.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Helpers can be included in your Grape endpoint as: helpers Grape::Helpers::ActiveModelSerializers
2+
3+
require 'active_model_serializers/serialization_context'
4+
25
module Grape
36
module Helpers
47
module ActiveModelSerializers
@@ -8,6 +11,12 @@ module ActiveModelSerializers
811
#
912
# Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
1013
def render(resource, active_model_serializer_options = {})
14+
active_model_serializer_options.fetch(:serialization_context) do
15+
active_model_serializer_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
16+
original_url: request.url[/\A[^?]+/],
17+
query_parameters: request.params
18+
)
19+
end
1120
env[:active_model_serializer_options] = active_model_serializer_options
1221
resource
1322
end

test/active_model_serializers/serialization_context_test_isolated.rb

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@
55
class SerializationContextTest < ActiveSupport::TestCase
66
include ActiveSupport::Testing::Isolation
77

8-
def create_request
9-
request = Minitest::Mock.new
10-
request.expect(:original_url, 'original_url')
11-
request.expect(:query_parameters, 'query_parameters')
12-
end
13-
148
class WithRails < SerializationContextTest
9+
def create_request
10+
request = ActionDispatch::Request.new({})
11+
def request.original_url
12+
'http://example.com/articles?page=2'
13+
end
14+
15+
def request.query_parameters
16+
{ 'page' => 2 }
17+
end
18+
request
19+
end
20+
1521
setup do
1622
require 'rails'
1723
require 'active_model_serializers'
@@ -20,8 +26,8 @@ class WithRails < SerializationContextTest
2026
end
2127

2228
test 'create context with request url and query parameters' do
23-
assert_equal @context.request_url, 'original_url'
24-
assert_equal @context.query_parameters, 'query_parameters'
29+
assert_equal @context.request_url, 'http://example.com/articles'
30+
assert_equal @context.query_parameters, 'page' => 2
2531
end
2632

2733
test 'url_helpers is set up for Rails url_helpers' do
@@ -36,14 +42,21 @@ class WithRails < SerializationContextTest
3642
end
3743

3844
class WithoutRails < SerializationContextTest
45+
def create_request
46+
{
47+
request_url: 'http://example.com/articles',
48+
query_parameters: { 'page' => 2 }
49+
}
50+
end
51+
3952
setup do
4053
require 'active_model_serializers/serialization_context'
4154
@context = ActiveModelSerializers::SerializationContext.new(create_request)
4255
end
4356

4457
test 'create context with request url and query parameters' do
45-
assert_equal @context.request_url, 'original_url'
46-
assert_equal @context.query_parameters, 'query_parameters'
58+
assert_equal @context.request_url, 'http://example.com/articles'
59+
assert_equal @context.query_parameters, 'page' => 2
4760
end
4861

4962
test 'url_helpers is a module when Rails is not present' do

test/adapter/json_api/pagination_links_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ def test_not_showing_pagination_links
161161

162162
assert_equal expected_response_without_pagination_links, adapter.serializable_hash
163163
end
164+
165+
def test_raises_descriptive_error_when_serialization_context_unset
166+
render_options = { adapter: :json_api }
167+
adapter = serializable(using_kaminari, render_options)
168+
exception = assert_raises do
169+
adapter.as_json
170+
end
171+
exception_class = ActiveModelSerializers::Adapter::JsonApi::PaginationLinks::MissingSerializationContextError
172+
assert_equal exception_class, exception.class
173+
assert_match(/CollectionSerializer#paginated\?/, exception.message)
174+
end
164175
end
165176
end
166177
end

0 commit comments

Comments
 (0)