Skip to content

Commit

Permalink
Fix rails-api#1759, Grape integration, adds serialization_context
Browse files Browse the repository at this point in the history
- 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?`.
  • Loading branch information
bf4 committed May 31, 2016
1 parent b8af289 commit f685c8c
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Features:
- [#1426](https://github.com/rails-api/active_model_serializers/pull/1426) Add ActiveModelSerializers.config.default_includes (@empact)

Fixes:
- [#1754](https://github.com/rails-api/active_model_serializers/pull/1754) Fixes #1759, Grape integration, improves serialization_context
missing error message on pagination. Document overriding CollectionSerializer#paginated?. (@bf4)
- [#1710](https://github.com/rails-api/active_model_serializers/pull/1710) Prevent association loading when `include_data` option
is set to `false`. (@groyoh)
- [#1747](https://github.com/rails-api/active_model_serializers/pull/1747) Improve jsonapi mime type registration for Rails 5 (@remear)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ module ActiveModelSerializers
module Adapter
class JsonApi < Base
class PaginationLinks
MissingSerializationContextError = Class.new(KeyError)
FIRST_PAGE = 1

attr_reader :collection, :context

def initialize(collection, adapter_options)
@collection = collection
@adapter_options = adapter_options
@context = adapter_options.fetch(:serialization_context)
@context = adapter_options.fetch(:serialization_context) do
fail MissingSerializationContextError, 'JsonApi::PaginationLinks requires a'\
"ActiveModelSerializers::SerializationContext.\n"\
"Please pass a ':serialization_context' option or override CollectionSerializer#paginated?"\
"to return 'false'.".freeze
end
end

def as_json
Expand Down
13 changes: 10 additions & 3 deletions lib/active_model_serializers/serialization_context.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'active_support/core_ext/array/extract_options'
module ActiveModelSerializers
class SerializationContext
class << self
Expand All @@ -22,9 +23,15 @@ def default_url_options

attr_reader :request_url, :query_parameters, :key_transform

def initialize(request, options = {})
@request_url = request.original_url[/\A[^?]+/]
@query_parameters = request.query_parameters
def initialize(*args)
options = args.extract_options!
if args.size == 1
request = args.pop
options[:request_url] = request.original_url[/\A[^?]+/]
options[:query_parameters] = request.query_parameters
end
@request_url = options.delete(:request_url)
@query_parameters = options.delete(:query_parameters)
@url_helpers = options.delete(:url_helpers) || self.class.url_helpers
@default_url_options = options.delete(:default_url_options) || self.class.default_url_options
end
Expand Down
9 changes: 9 additions & 0 deletions lib/grape/helpers/active_model_serializers.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Helpers can be included in your Grape endpoint as: helpers Grape::Helpers::ActiveModelSerializers

require 'active_model_serializers/serialization_context'

module Grape
module Helpers
module ActiveModelSerializers
Expand All @@ -8,6 +11,12 @@ module ActiveModelSerializers
#
# Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
def render(resource, active_model_serializer_options = {})
active_model_serializer_options.fetch(:serialization_context) do
active_model_serializer_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
original_url: request.url[/\A[^?]+/],
query_parameters: request.params
)
end
env[:active_model_serializer_options] = active_model_serializer_options
resource
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
class SerializationContextTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation

def create_request
request = Minitest::Mock.new
request.expect(:original_url, 'original_url')
request.expect(:query_parameters, 'query_parameters')
end

class WithRails < SerializationContextTest
def create_request
request = ActionDispatch::Request.new({})
def request.original_url
'http://example.com/articles?page=2'
end

def request.query_parameters
{ 'page' => 2 }
end
request
end

setup do
require 'rails'
require 'active_model_serializers'
Expand All @@ -20,8 +26,8 @@ class WithRails < SerializationContextTest
end

test 'create context with request url and query parameters' do
assert_equal @context.request_url, 'original_url'
assert_equal @context.query_parameters, 'query_parameters'
assert_equal @context.request_url, 'http://example.com/articles'
assert_equal @context.query_parameters, 'page' => 2
end

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

class WithoutRails < SerializationContextTest
def create_request
{
request_url: 'http://example.com/articles',
query_parameters: { 'page' => 2 }
}
end

setup do
require 'active_model_serializers/serialization_context'
@context = ActiveModelSerializers::SerializationContext.new(create_request)
end

test 'create context with request url and query parameters' do
assert_equal @context.request_url, 'original_url'
assert_equal @context.query_parameters, 'query_parameters'
assert_equal @context.request_url, 'http://example.com/articles'
assert_equal @context.query_parameters, 'page' => 2
end

test 'url_helpers is a module when Rails is not present' do
Expand Down
11 changes: 11 additions & 0 deletions test/adapter/json_api/pagination_links_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,17 @@ def test_not_showing_pagination_links

assert_equal expected_response_without_pagination_links, adapter.serializable_hash
end

def test_raises_descriptive_error_when_serialization_context_unset
render_options = { adapter: :json_api }
adapter = serializable(using_kaminari, render_options)
exception = assert_raises do
adapter.as_json
end
exception_class = ActiveModelSerializers::Adapter::JsonApi::PaginationLinks::MissingSerializationContextError
assert_equal exception_class, exception.class
assert_match(/CollectionSerializer#paginated\?/, exception.message)
end
end
end
end
Expand Down

0 comments on commit f685c8c

Please sign in to comment.