Test caching with fragmented key

- on association, fix up assocation logic
- on attribute
This commit is contained in:
Benjamin Fleischer 2016-06-07 03:57:24 -05:00
parent b8924157d7
commit 5375e009e2
4 changed files with 53 additions and 35 deletions

View File

@ -70,9 +70,9 @@ module ActiveModel
def fragmented_attributes def fragmented_attributes
cached = _cache_only ? _cache_only : _attributes - _cache_except cached = _cache_only ? _cache_only : _attributes - _cache_except
cached = cached.map! {|field| _attributes_keys.fetch(field, field) } cached = cached.map! { |field| _attributes_keys.fetch(field, field) }
non_cached = _attributes - cached non_cached = _attributes - cached
non_cached = non_cached.map! {|field| _attributes_keys.fetch(field, field) } non_cached = non_cached.map! { |field| _attributes_keys.fetch(field, field) }
{ {
cached: cached, cached: cached,
non_cached: non_cached non_cached: non_cached
@ -233,28 +233,20 @@ module ActiveModel
def fetch_attributes_fragment(adapter_instance) def fetch_attributes_fragment(adapter_instance)
self.class._cache_options ||= {} self.class._cache_options ||= {}
self.class._cache_options[:key] = self.class._cache_key if self.class._cache_key self.class._cache_options[:key] = self.class._cache_key if self.class._cache_key
options = { include_directive: ActiveModel::Serializer.include_directive_from_options({})}
fields = self.class.fragmented_attributes fields = self.class.fragmented_attributes
non_cached_fields = fields[:non_cached].dup non_cached_fields = fields[:non_cached].dup
non_cached_hash = attributes(non_cached_fields, true) non_cached_hash = attributes(non_cached_fields, true)
(non_cached_fields - non_cached_hash.keys).each do |missing_field| include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys)
# TODO: use _attributes_keys? non_cached_hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance)
# gets any other associations, etc.
non_cached_hash[missing_field] = read_attribute_for_serialization(missing_field)
end
cached_fields = fields[:cached].dup cached_fields = fields[:cached].dup
key = cache_key(adapter_instance) key = cache_key(adapter_instance)
cached_hash = cached_hash =
self.class.cache_store.fetch(key, self.class._cache_options) do self.class.cache_store.fetch(key, self.class._cache_options) do
hash = attributes(cached_fields, true) hash = attributes(cached_fields, true)
(cached_fields - hash.keys).each do |missing_field| include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys)
# TODO: use _attributes_keys? hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance)
# gets any other associations, etc.
hash[missing_field] = read_attribute_for_serialization(missing_field)
end
hash
end end
# Merge both results # Merge both results

View File

@ -123,7 +123,7 @@ module ActionController
id: 42, id: 42,
lat: '-23.550520', lat: '-23.550520',
lng: '-46.633309', lng: '-46.633309',
place: 'Nowhere' # is a virtual attribute on LocationSerializer address: 'Nowhere' # is a virtual attribute on LocationSerializer
} }
] ]
} }

View File

@ -127,7 +127,7 @@ module ActiveModelSerializers
end end
def test_fragment_cache_definition def test_fragment_cache_definition
assert_equal([:name], @role_serializer.class._cache_only) assert_equal([:name, :slug], @role_serializer.class._cache_only)
assert_equal([:content], @bio_serializer.class._cache_except) assert_equal([:content], @bio_serializer.class._cache_except)
end end
@ -178,14 +178,14 @@ module ActiveModelSerializers
id: @location.id, id: @location.id,
lat: @location.lat, lat: @location.lat,
lng: @location.lng, lng: @location.lng,
place: 'Nowhere' address: 'Nowhere'
} }
hash = render_object_with_cache(@location) hash = render_object_with_cache(@location)
assert_equal(hash, expected_result) assert_equal(hash, expected_result)
key = "#{@location.cache_key}/#{adapter.cache_key}" key = "#{@location.cache_key}/#{adapter.cache_key}"
assert_equal({ place: 'Nowhere' }, cache_store.fetch(key)) assert_equal({ address: 'Nowhere' }, cache_store.fetch(key))
end end
def test_fragment_cache_with_inheritance def test_fragment_cache_with_inheritance
@ -434,21 +434,46 @@ module ActiveModelSerializers
end end
def test_fragment_fetch_with_virtual_attributes def test_fragment_fetch_with_virtual_attributes
@author = Author.new(name: 'Joao M. D. Moura') author = Author.new(name: 'Joao M. D. Moura')
@role = Role.new(name: 'Great Author', description: nil) role = Role.new(name: 'Great Author', description: nil)
@role.author = [@author] role.author = [author]
@role_serializer = RoleSerializer.new(@role) role_serializer = RoleSerializer.new(role)
adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(@role_serializer) adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(role_serializer)
@role_hash = @role_serializer.fetch_attributes_fragment(adapter_instance)
expected_result = { expected_result = {
id: @role.id, id: role.id,
description: @role.description, description: role.description,
slug: "#{@role.name}-#{@role.id}", slug: "#{role.name}-#{role.id}",
name: @role.name name: role.name
} }
cache_store.clear
assert_equal(@role_hash, expected_result) role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)
assert_equal(role_hash, expected_result)
role.attributes[:id] = 'this has been updated'
role.name = 'this was cached'
role_hash = role_serializer.fetch_attributes_fragment(adapter_instance)
assert_equal(expected_result.merge(id: role.id), role_hash)
end
def test_fragment_fetch_with_except
adapter_instance = ActiveModelSerializers::Adapter.configured_adapter.new(@bio_serializer)
expected_result = {
id: @bio.id,
rating: nil,
content: @bio.content
}
cache_store.clear
bio_hash = @bio_serializer.fetch_attributes_fragment(adapter_instance)
assert_equal(expected_result, bio_hash)
@bio.content = 'this has been updated'
@bio.rating = 'this was cached'
bio_hash = @bio_serializer.fetch_attributes_fragment(adapter_instance)
assert_equal(expected_result.merge(content: @bio.content), bio_hash)
end end
def test_fragment_fetch_with_namespaced_object def test_fragment_fetch_with_namespaced_object

11
test/fixtures/poro.rb vendored
View File

@ -136,10 +136,11 @@ AuthorSerializer = Class.new(ActiveModel::Serializer) do
end end
RoleSerializer = Class.new(ActiveModel::Serializer) do RoleSerializer = Class.new(ActiveModel::Serializer) do
cache only: [:name], skip_digest: true cache only: [:name, :slug], skip_digest: true
attributes :id, :name, :description, :slug attributes :id, :name, :description
attribute :friendly_id, key: :slug
def slug def friendly_id
"#{object.name}-#{object.id}" "#{object.name}-#{object.id}"
end end
@ -153,10 +154,10 @@ LikeSerializer = Class.new(ActiveModel::Serializer) do
end end
LocationSerializer = Class.new(ActiveModel::Serializer) do LocationSerializer = Class.new(ActiveModel::Serializer) do
cache only: [:place], skip_digest: true cache only: [:address], skip_digest: true
attributes :id, :lat, :lng attributes :id, :lat, :lng
belongs_to :place belongs_to :place, key: :address
def place def place
'Nowhere' 'Nowhere'