From cdc59394567dec43fc7a85f6663e77f1c16f6613 Mon Sep 17 00:00:00 2001 From: Larry Gebhardt Date: Fri, 15 Jan 2021 11:20:12 -0500 Subject: [PATCH] Use to_f for hash_cache_field to get millisecond precision for ActiveSupport::TimeWithZone timestamps --- lib/jsonapi/basic_resource.rb | 9 ++++++++- test/fixtures/posts.yml | 2 ++ test/unit/resource/resource_test.rb | 29 ++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/jsonapi/basic_resource.rb b/lib/jsonapi/basic_resource.rb index c4e27de70..5b687de85 100644 --- a/lib/jsonapi/basic_resource.rb +++ b/lib/jsonapi/basic_resource.rb @@ -1019,7 +1019,14 @@ def attribute_caching_context(_context) # Generate a hashcode from the value to be used as part of the cache lookup def hash_cache_field(value) - Digest::MD5.hexdigest(value.to_s) + if value.nil? + nil + elsif value.is_a?(ActiveSupport::TimeWithZone) + # for timestamps use to_f instead of computing a hash + value.to_f + else + Digest::MD5.hexdigest(value) + end end def _model_class diff --git a/test/fixtures/posts.yml b/test/fixtures/posts.yml index 02d94ef3f..902c7d980 100644 --- a/test/fixtures/posts.yml +++ b/test/fixtures/posts.yml @@ -3,6 +3,8 @@ post_1: title: New post body: A body!!! author_id: 1001 + created_at: 2020-01-01 14:15:16 UTC + updated_at: 2020-01-15 14:15:12 UTC post_2: id: 2 diff --git a/test/unit/resource/resource_test.rb b/test/unit/resource/resource_test.rb index 10f8b1e13..62dc7e397 100644 --- a/test/unit/resource/resource_test.rb +++ b/test/unit/resource/resource_test.rb @@ -95,7 +95,7 @@ class PostWithReadonlyAttributesResource < JSONAPI::Resource class ResourceTest < ActiveSupport::TestCase def setup - @post = Post.first + @post = posts(:post_1) end def test_model_name @@ -126,6 +126,33 @@ def test_resource_for_resource_does_not_exist_at_root end end + def test_cache_ids_are_consistent_from_run_to_run + assert_equal '2020-01-15 14:15:12 UTC', @post.updated_at.to_s + + post_resource = PostResource.new(@post, {}) + assert_equal [@post.id, 1579097712.0], post_resource.cache_id + end + + def test_cache_ids_change_when_cache_field_is_changed + assert_equal '2020-01-15 14:15:12 UTC', @post.updated_at.to_s + + post_resource = PostResource.new(@post, {}) + assert_equal [@post.id, 1579097712.0], post_resource.cache_id + + assert @post.touch + refute_equal [@post.id, 1579097712.0], post_resource.cache_id + end + + def test_date_based_cache_ids_change_with_milliseconds_if_hash_cache_field_is_time_stamp + assert_equal '2020-01-15 14:15:12 UTC', @post.updated_at.to_s + + post_resource = PostResource.new(@post, {}) + assert_equal [@post.id, 1579097712.0], post_resource.cache_id + + @post.updated_at = @post.updated_at + 0.222 + refute_equal [@post.id, 1579097712.0], post_resource.cache_id + end + def test_resource_for_with_underscored_namespaced_paths assert_equal(JSONAPI::Resource.resource_klass_for('my_module/related'), MyModule::RelatedResource) assert_equal(PostResource.resource_klass_for('my_module/related'), MyModule::RelatedResource)