summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Barbosa Alexandre <dbalexandre@gmail.com>2019-02-26 23:03:39 -0300
committerDouglas Barbosa Alexandre <dbalexandre@gmail.com>2019-02-28 14:11:04 -0300
commite96f2f248a63cc7115fb52a02b1743f15205e642 (patch)
treeb42d9b1745cf917d6a9d815e02060fa2882d1076
parent790a51a42778b3aa3fb5c8c5afe687ef06dd4433 (diff)
downloadgitlab-ce-e96f2f248a63cc7115fb52a02b1743f15205e642.tar.gz
Mark cached value as persisted when is an instance of ActiveRecord::Base
-rw-r--r--lib/gitlab/json_cache.rb16
-rw-r--r--spec/lib/gitlab/json_cache_spec.rb28
2 files changed, 42 insertions, 2 deletions
diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb
index 1adf83739ad..24daad638f4 100644
--- a/lib/gitlab/json_cache.rb
+++ b/lib/gitlab/json_cache.rb
@@ -71,7 +71,21 @@ module Gitlab
end
def parse_entry(raw, klass)
- klass.new(raw) if valid_entry?(raw, klass)
+ return unless valid_entry?(raw, klass)
+ return klass.new(raw) unless klass.ancestors.include?(ActiveRecord::Base)
+
+ # When the cached value is a persisted instance of ActiveRecord::Base in
+ # some cases a relation can return an empty collection becauses scope.none!
+ # is being applied on ActiveRecord::Associations::CollectionAssociation#scope
+ # when the new_record? method incorrectly returns false.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab-ee/issues/9903#note_145329964
+ attributes = klass.attributes_builder.build_from_database(raw, {})
+ klass.allocate.init_with("attributes" => attributes, "new_record" => new_record?(raw, klass))
+ end
+
+ def new_record?(raw, klass)
+ raw.fetch(klass.primary_key, nil).blank?
end
def valid_entry?(raw, klass)
diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb
index b52078e8556..2cae8ec031a 100644
--- a/spec/lib/gitlab/json_cache_spec.rb
+++ b/spec/lib/gitlab/json_cache_spec.rb
@@ -297,13 +297,39 @@ describe Gitlab::JsonCache do
expect(result).to eq(broadcast_message)
end
+ context 'when the cached value is an instance of ActiveRecord::Base' do
+ it 'returns a persisted record when id is set' do
+ backend.write(expanded_key, broadcast_message.to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_persisted
+ end
+
+ it 'returns a new record when id is nil' do
+ backend.write(expanded_key, build(:broadcast_message).to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_new_record
+ end
+
+ it 'returns a new record when id is missing' do
+ backend.write(expanded_key, build(:broadcast_message).attributes.except('id').to_json)
+
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to be_new_record
+ end
+ end
+
it "returns the result of the block when 'as' option is nil" do
result = cache.fetch(key, as: nil) { 'block result' }
expect(result).to eq('block result')
end
- it "returns the result of the block when 'as' option is not informed" do
+ it "returns the result of the block when 'as' option is missing" do
result = cache.fetch(key) { 'block result' }
expect(result).to eq('block result')