Skip to content

Commit 12e0278

Browse files
authored
MONGOID-5306 Use pluck instead of only to avoid projecting when referencing association _ids (#5253)
* MONGOID-5306 Referencing unset attributes erroneously produces MissingAttributeError when model was not obtained using a query with projection * MONGOID-5306 remove byebugs
1 parent 886da80 commit 12e0278

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

lib/mongoid/association/accessors.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ def self.define_ids_getter!(association)
319319
ids_method = "#{association.name.to_s.singularize}_ids"
320320
association.inverse_class.tap do |klass|
321321
klass.re_define_method(ids_method) do
322-
send(association.name).only(:_id).map(&:_id)
322+
send(association.name).pluck(:_id)
323323
end
324324
end
325325
end

spec/mongoid/interceptable_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,4 +2353,21 @@ class TestClass
23532353
end
23542354
end
23552355
end
2356+
2357+
# This case is rather niche. The _ids method used to use the `.only` method
2358+
# to get only the _ids for an association, which was causing a
2359+
# MissingAttributeError to be raised when accessing another association. This
2360+
# was fixed by using `.pluck` over `.only`. Look at MONGOID-5306 for a more
2361+
# detailed explanation.
2362+
context "when accessing _ids in validate and access an association in after_initialize" do
2363+
it "doesn't raise a MissingAttributeError" do
2364+
company = InterceptableCompany.create!
2365+
shop = InterceptableShop.create!(company: company)
2366+
user = InterceptableUser.new
2367+
user.company = company
2368+
expect do
2369+
user.save!
2370+
end.to_not raise_error(ActiveModel::MissingAttributeError)
2371+
end
2372+
end
23562373
end

spec/mongoid/interceptable_spec_models.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,41 @@ class InterceptableEngine
267267

268268
field :_id, type: String, default: -> { "hello-engine-#{wing&.id}" }
269269
end
270+
271+
class InterceptableCompany
272+
include Mongoid::Document
273+
274+
has_many :users, class_name: "InterceptableUser"
275+
has_many :shops, class_name: "InterceptableShop"
276+
end
277+
278+
class InterceptableShop
279+
include Mongoid::Document
280+
281+
embeds_one :address, class_name: "InterceptableAddress"
282+
belongs_to :company, class_name: "InterceptableCompany"
283+
284+
after_initialize :build_address1
285+
286+
def build_address1
287+
self.address ||= Address.new
288+
end
289+
end
290+
291+
class InterceptableAddress
292+
include Mongoid::Document
293+
embedded_in :shop, class_name: "InterceptableShop"
294+
end
295+
296+
class InterceptableUser
297+
include Mongoid::Document
298+
299+
belongs_to :company, class_name: "InterceptableCompany"
300+
301+
validate :break_mongoid
302+
303+
def break_mongoid
304+
company.shop_ids
305+
end
306+
end
307+

0 commit comments

Comments
 (0)