mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
Merge pull request #1650 from bf4/fix_serialization_scope
[FIX] serialization scope options
This commit is contained in:
commit
7acbb765bd
@ -3,6 +3,9 @@
|
|||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
- [#1650](https://github.com/rails-api/active_model_serializers/pull/1650) Fix serialization scope options `scope`, `scope_name`
|
||||||
|
take precedence over `serialization_scope` in the controller.
|
||||||
|
Fix tests that required tearing down dynamic methods. (@bf4)
|
||||||
- [#1644](https://github.com/rails-api/active_model_serializers/pull/1644) Include adapter name in cache key so
|
- [#1644](https://github.com/rails-api/active_model_serializers/pull/1644) Include adapter name in cache key so
|
||||||
that the same serializer can be cached per adapter. (@bf4 via #1346 by @kevintyll)
|
that the same serializer can be cached per adapter. (@bf4 via #1346 by @kevintyll)
|
||||||
- [#1642](https://github.com/rails-api/active_model_serializers/pull/1642) Prefer object.cache_key over the generated
|
- [#1642](https://github.com/rails-api/active_model_serializers/pull/1642) Prefer object.cache_key over the generated
|
||||||
|
|||||||
@ -30,8 +30,8 @@ module ActionController
|
|||||||
options[:adapter] = false
|
options[:adapter] = false
|
||||||
end
|
end
|
||||||
serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
|
serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
|
||||||
serializable_resource.serialization_scope ||= serialization_scope
|
serializable_resource.serialization_scope ||= options.fetch(:scope) { serialization_scope }
|
||||||
serializable_resource.serialization_scope_name = _serialization_scope
|
serializable_resource.serialization_scope_name = options.fetch(:scope_name) { _serialization_scope }
|
||||||
# For compatibility with the JSON renderer: `json.to_json(options) if json.is_a?(String)`.
|
# For compatibility with the JSON renderer: `json.to_json(options) if json.is_a?(String)`.
|
||||||
# Otherwise, since `serializable_resource` is not a string, the renderer would call
|
# Otherwise, since `serializable_resource` is not a string, the renderer would call
|
||||||
# `to_json` on a String and given odd results, such as `"".to_json #=> '""'`
|
# `to_json` on a String and given odd results, such as `"".to_json #=> '""'`
|
||||||
|
|||||||
@ -96,16 +96,18 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self._serializer_instance_method_defined?(name)
|
# rubocop:disable Style/ClassVars
|
||||||
_serializer_instance_methods.include?(name)
|
def self.method_added(method_name)
|
||||||
|
@@_serializer_instance_methods ||= Hash.new { |h, k| h[k] = Set.new }
|
||||||
|
@@_serializer_instance_methods[self] << method_name
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Fix load-order failures when different serializer instances define different
|
def self._serializer_instance_method_defined?(name)
|
||||||
# scope methods
|
@_serializer_instance_methods ||= (ActiveModel::Serializer.public_instance_methods - Object.public_instance_methods).to_set
|
||||||
def self._serializer_instance_methods
|
@_serializer_instance_methods.include?(name) ||
|
||||||
@_serializer_instance_methods ||= (public_instance_methods - Object.public_instance_methods).to_set
|
@@_serializer_instance_methods[self].include?(name)
|
||||||
end
|
end
|
||||||
private_class_method :_serializer_instance_methods
|
# rubocop:enable Style/ClassVars
|
||||||
|
|
||||||
attr_accessor :object, :root, :scope
|
attr_accessor :object, :root, :scope
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,17 @@
|
|||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
module SerializationScopeTesting
|
module SerializationScopeTesting
|
||||||
|
def self.undef_serializer_dynamic_scope_methods
|
||||||
|
[PostSerializer, PostViewContextSerializer]. each do |serializer_class|
|
||||||
|
instance_method_cache = serializer_class.instance_variable_get(:@_serializer_instance_methods)
|
||||||
|
class_method_cache = serializer_class.class_variable_get(:@@_serializer_instance_methods)[serializer_class]
|
||||||
|
[:view_context, :current_user].each do |scope_method|
|
||||||
|
serializer_class.send(:undef_method, scope_method) if serializer_class.method_defined?(scope_method)
|
||||||
|
instance_method_cache && instance_method_cache.delete(scope_method)
|
||||||
|
class_method_cache && class_method_cache.delete(scope_method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
class User < ActiveModelSerializers::Model
|
class User < ActiveModelSerializers::Model
|
||||||
attr_accessor :id, :name, :admin
|
attr_accessor :id, :name, :admin
|
||||||
def admin?
|
def admin?
|
||||||
@ -70,6 +81,10 @@ module SerializationScopeTesting
|
|||||||
class DefaultScopeTest < ActionController::TestCase
|
class DefaultScopeTest < ActionController::TestCase
|
||||||
tests PostTestController
|
tests PostTestController
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
SerializationScopeTesting.undef_serializer_dynamic_scope_methods
|
||||||
|
end
|
||||||
|
|
||||||
def test_default_serialization_scope
|
def test_default_serialization_scope
|
||||||
assert_equal :current_user, @controller._serialization_scope
|
assert_equal :current_user, @controller._serialization_scope
|
||||||
end
|
end
|
||||||
@ -120,6 +135,10 @@ module SerializationScopeTesting
|
|||||||
end
|
end
|
||||||
tests PostViewContextTestController
|
tests PostViewContextTestController
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
SerializationScopeTesting.undef_serializer_dynamic_scope_methods
|
||||||
|
end
|
||||||
|
|
||||||
def test_defined_serialization_scope
|
def test_defined_serialization_scope
|
||||||
assert_equal :view_context, @controller._serialization_scope
|
assert_equal :view_context, @controller._serialization_scope
|
||||||
end
|
end
|
||||||
@ -158,8 +177,6 @@ module SerializationScopeTesting
|
|||||||
assert_equal expected_json, @response.body
|
assert_equal expected_json, @response.body
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# FIXME: Has bugs. See comments below and
|
|
||||||
# https://github.com/rails-api/active_model_serializers/issues/1509
|
|
||||||
class NilSerializationScopeTest < ActionController::TestCase
|
class NilSerializationScopeTest < ActionController::TestCase
|
||||||
class PostViewContextTestController < ActionController::Base
|
class PostViewContextTestController < ActionController::Base
|
||||||
serialization_scope nil
|
serialization_scope nil
|
||||||
@ -171,12 +188,15 @@ module SerializationScopeTesting
|
|||||||
render json: new_post, serializer: PostSerializer, adapter: :json
|
render json: new_post, serializer: PostSerializer, adapter: :json
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: run test when
|
def render_post_with_passed_in_scope
|
||||||
# global state in Serializer._serializer_instance_methods is fixed
|
self.current_user = User.new(id: 3, name: 'Pete', admin: false)
|
||||||
# def render_post_with_passed_in_scope
|
render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user, scope_name: :current_user
|
||||||
# self.current_user = User.new(id: 3, name: 'Pete', admin: false)
|
end
|
||||||
# render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user, scope_name: :current_user
|
|
||||||
# end
|
def render_post_with_passed_in_scope_without_scope_name
|
||||||
|
self.current_user = User.new(id: 3, name: 'Pete', admin: false)
|
||||||
|
render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
@ -186,6 +206,10 @@ module SerializationScopeTesting
|
|||||||
end
|
end
|
||||||
tests PostViewContextTestController
|
tests PostViewContextTestController
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
SerializationScopeTesting.undef_serializer_dynamic_scope_methods
|
||||||
|
end
|
||||||
|
|
||||||
def test_nil_serialization_scope
|
def test_nil_serialization_scope
|
||||||
assert_nil @controller._serialization_scope
|
assert_nil @controller._serialization_scope
|
||||||
end
|
end
|
||||||
@ -194,37 +218,35 @@ module SerializationScopeTesting
|
|||||||
assert_nil @controller.serialization_scope
|
assert_nil @controller.serialization_scope
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: change to NoMethodError and match 'admin?' when the
|
|
||||||
# global state in Serializer._serializer_instance_methods is fixed
|
|
||||||
def test_nil_scope
|
def test_nil_scope
|
||||||
if Rails.version.start_with?('4.0')
|
exception_matcher = /current_user/
|
||||||
exception_class = NoMethodError
|
exception = assert_raises(NameError) do
|
||||||
exception_matcher = 'admin?'
|
|
||||||
else
|
|
||||||
exception_class = NameError
|
|
||||||
exception_matcher = /admin|current_user/
|
|
||||||
end
|
|
||||||
exception = assert_raises(exception_class) do
|
|
||||||
get :render_post_with_no_scope
|
get :render_post_with_no_scope
|
||||||
end
|
end
|
||||||
assert_match exception_matcher, exception.message
|
assert_match exception_matcher, exception.message
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: run test when
|
def test_serialization_scope_is_and_nil_scope_passed_in_current_user
|
||||||
# global state in Serializer._serializer_instance_methods is fixed
|
get :render_post_with_passed_in_scope
|
||||||
# def test_nil_scope_passed_in_current_user
|
expected_json = {
|
||||||
# get :render_post_with_passed_in_scope
|
post: {
|
||||||
# expected_json = {
|
id: 4,
|
||||||
# post: {
|
title: 'Title',
|
||||||
# id: 4,
|
body: "The 'scope' is the 'current_user': true",
|
||||||
# title: 'Title',
|
comments: [
|
||||||
# body: "The 'scope' is the 'current_user': true",
|
{ id: 2, body: 'Scoped' }
|
||||||
# comments: [
|
]
|
||||||
# { id: 2, body: 'Scoped' }
|
}
|
||||||
# ]
|
}.to_json
|
||||||
# }
|
assert_equal expected_json, @response.body
|
||||||
# }.to_json
|
end
|
||||||
# assert_equal expected_json, @response.body
|
|
||||||
# end
|
def test_serialization_scope_is_nil_and_scope_passed_in_current_user_without_scope_name
|
||||||
|
exception_matcher = /current_user/
|
||||||
|
exception = assert_raises(NameError) do
|
||||||
|
get :render_post_with_passed_in_scope_without_scope_name
|
||||||
|
end
|
||||||
|
assert_match exception_matcher, exception.message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user