Skip to content

Commit 7ce3f07

Browse files
authored
MONGOID-5077 DocumentNotFound message fails to account for shard key (#5292)
* MONGOID-5077 DocumentNotFound message fails to account for shard key * MONGOID-5077 change some language * MONGOID-5077 slice by shard key * MONGOID-5077 remove unnecessary code
1 parent 9ed3c63 commit 7ce3f07

File tree

4 files changed

+90
-8
lines changed

4 files changed

+90
-8
lines changed

lib/config/locales/en.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ en:
7272
resolution: "Search for attributes that are in the database or set
7373
the Mongoid.raise_not_found_error configuration option to false,
7474
which will cause a nil to be returned instead of raising this error."
75+
document_with_shard_key_not_found:
76+
message: "Document not found for class %{klass} with id %{missing} and
77+
shard key %{shard_key}."
78+
summary: "When calling %{klass}.find with an id and a shard key, each
79+
parameter must match a document in the database or this error will
80+
be raised. The search was for the id: %{missing} with
81+
shard_key: %{shard_key} and it was not found."
82+
resolution: "Search for an id/shard key that is in the database or set
83+
the Mongoid.raise_not_found_error configuration option to false,
84+
which will cause a nil to be returned instead of raising this error."
7585
empty_config_file:
7686
message: "Empty configuration file: %{path}."
7787
summary: "Your mongoid.yml configuration file appears to be empty."

lib/mongoid/errors/document_not_found.rb

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class DocumentNotFound < MongoidError
2020
#
2121
# @param [ Class ] klass The model class.
2222
# @param [ Hash, Array, Object ] params The attributes or ids.
23-
# @param [ Array ] unmatched The unmatched ids, if appropriate
23+
# @param [ Array, Hash ] unmatched The unmatched ids, if appropriate. If
24+
# there is a shard key this will be a hash.
2425
def initialize(klass, params, unmatched = nil)
2526
if !unmatched && !params.is_a?(Hash)
2627
unmatched = Array(params)
@@ -29,13 +30,14 @@ def initialize(klass, params, unmatched = nil)
2930
@klass, @params = klass, params
3031
super(
3132
compose_message(
32-
message_key(params),
33+
message_key(params, unmatched),
3334
{
3435
klass: klass.name,
3536
searched: searched(params),
3637
attributes: params,
3738
total: total(params),
38-
missing: missing(unmatched)
39+
missing: missing(unmatched),
40+
shard_key: shard_key(unmatched)
3941
}
4042
)
4143
)
@@ -54,6 +56,8 @@ def initialize(klass, params, unmatched = nil)
5456
def missing(unmatched)
5557
if unmatched.is_a?(::Array)
5658
unmatched.join(", ")
59+
elsif unmatched.is_a?(::Hash)
60+
unmatched[:_id] || unmatched["_id"]
5761
else
5862
unmatched
5963
end
@@ -93,10 +97,25 @@ def total(params)
9397
# error.problem
9498
#
9599
# @return [ String ] The problem.
96-
def message_key(params)
97-
case params
98-
when Hash then "document_with_attributes_not_found"
99-
else "document_not_found"
100+
def message_key(params, unmatched)
101+
if Hash === params
102+
"document_with_attributes_not_found"
103+
elsif Hash === unmatched && unmatched.size >= 2
104+
"document_with_shard_key_not_found"
105+
else
106+
"document_not_found"
107+
end
108+
end
109+
110+
# Get the shard key from the unmatched hash.
111+
#
112+
# @return [ String ] the shard key and value.
113+
def shard_key(unmatched)
114+
if Hash === unmatched
115+
h = unmatched.dup
116+
h.delete("_id")
117+
h.delete(:_id)
118+
h.map{|k,v| "#{k}: #{v}" }.join(", ")
100119
end
101120
end
102121
end

lib/mongoid/reloadable.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def reload
2323

2424
reloaded = _reload
2525
if Mongoid.raise_not_found_error && (reloaded.nil? || reloaded.empty?)
26-
raise Errors::DocumentNotFound.new(self.class, _id, _id)
26+
shard_keys = atomic_selector.with_indifferent_access.slice(*shard_key_fields, :_id)
27+
raise Errors::DocumentNotFound.new(self.class, _id, shard_keys)
2728
end
2829
@attributes = reloaded
2930
@attributes_before_type_cast = {}

spec/mongoid/errors/document_not_found_spec.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,58 @@
8080
)
8181
end
8282
end
83+
84+
context "when providing an _id and a shard key" do
85+
86+
let(:id) { BSON::ObjectId.new }
87+
let(:doc) { { _id: id, a: "syd" } }
88+
let(:error) do
89+
described_class.new(Person, id, doc)
90+
end
91+
92+
it "contains the problem in the message" do
93+
expect(error.message).to include(
94+
"Document not found for class Person with id #{id.to_s} and shard key a: syd."
95+
)
96+
end
97+
98+
it "contains the summary in the message" do
99+
expect(error.message).to include(
100+
"When calling Person.find with an id and a shard key"
101+
)
102+
end
103+
104+
it "contains the resolution in the message" do
105+
expect(error.message).to include(
106+
"Search for an id/shard key that is in the database or set"
107+
)
108+
end
109+
end
110+
111+
context "when providing an id in a hash without a shard key" do
112+
113+
let(:error) do
114+
described_class.new(Person, 1, { _id: 1 })
115+
end
116+
117+
it "contains the problem in the message" do
118+
expect(error.message).to include(
119+
"Document(s) not found for class Person with id(s) 1."
120+
)
121+
end
122+
123+
it "contains the summary in the message" do
124+
expect(error.message).to include(
125+
"When calling Person.find with an id or array of ids"
126+
)
127+
end
128+
129+
it "contains the resolution in the message" do
130+
expect(error.message).to include(
131+
"Search for an id that is in the database or set the"
132+
)
133+
end
134+
end
83135
end
84136

85137
describe "#params" do

0 commit comments

Comments
 (0)