0

A User class has many devices and deleted_devices. Relationships of User Class:

has_many :devices, class_name: "Device", validate: false, autosave: true, dependent: :destroy
        
has_many :deleted_devices, class_name: "DeletedDevice", validate: false, autosave: true, dependent: :destroy

Consider user1 object of User class. When I destroy the user1 by user1.destroy() All devices and deleted_devices associated with user1 get destroyed.

I want to transfer deleted_devices of user1 to user2 such that when all deleted_devices of user1 get combined with deleted_devices of user2.

Options tried but didn't work:

user2.deleted_devices.merge!(user1.deleted_devices)

user2.deleted_devices.merge(user1.deleted_devices)

user2.deleted_devices+=user1.deleted_devices

Used above options to achieve the same but when I did user1.destroy, user1 deleted_devices also get removed from user2 deleted_devices.

How can I achieve the same?

Hermione
  • 53
  • 3

1 Answers1

0

I did some digging around and there does seem to be some confusing behaviour with Mongoid associations, but I found a method that works.

Setup

Given the following:

irb(main):001:0> user1 = User.create!
irb(main):002:0> user2 = User.create!
irb(main):003:0> 
irb(main):004:0> device = user1.deleted_devices.create!

Test with #merge!

user2.merge! doesn't work, and the association remains empty:

irb(main):006:0> user2.deleted_devices.merge!(user1.deleted_devices)
irb(main):007:0> user2.deleted_devices
=> []

and device still belongs to user1

irb(main):008:0> device.user == user2
=> false
irb(main):009:0> device.user == user1
=> true

Test with #update

Let's explore a bit. At first glance, it seems like #update might work:

irb(main):006:1* user1.deleted_devices.each do |dd|
irb(main):007:1*   dd.update(user: user2)
irb(main):008:0> end
irb(main):009:0> device.user == user2
=> true
irb(main):010:0> device.user == user1
=> false

but user1's association still contains device (and confusingly, so does user2's), so destroying it would destroy device too:

irb(main):011:0> user2.deleted_devices
=> [#<DeletedDevice _id: 63833fb82efba308139e9d38, created_at: 2022-11-27 10:45:12.538566 UTC, updated_at: 2022-11-27 10:45:19.352898 UTC, user_id: BSON::ObjectId('63833fb82efba308139e9d37')>]
irb(main):012:0> user1.deleted_devices
=> [#<DeletedDevice _id: 63833fb82efba308139e9d38, created_at: 2022-11-27 10:45:12.538566 UTC, updated_at: 2022-11-27 10:45:19.352898 UTC, user_id: BSON::ObjectId('63833fb82efba308139e9d37')>]
irb(main):013:0> user1.destroy
=> true
irb(main):014:0> device.reload
/Users/pmv/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/mongoid-8.0.2/lib/mongoid/reloadable.rb:27:in `reload':  (Mongoid::Errors::DocumentNotFound)
message:
  Document(s) not found for class DeletedDevice with id(s) 63833fb82efba308139e9d38.

Doing user1.destroyed_devices.clear before deleting it might do the trick, and that doesn't fire callbacks, but it's far from ideal.

Success with <<

This however appears to work for me:

irb(main):006:0> user2.deleted_devices << user1.deleted_devices
=> [#<DeletedDevice _id: 638340dd2efba3084a1b36af, created_at: 2022-11-27 10:50:05.692256 UTC, updated_at: 2022-11-27 10:50:12.892345 UTC, user_id: BSON::ObjectId('638340dd2efba3084a1b36ae')>]
irb(main):007:0> user2.deleted_devices.count
=> 1
irb(main):008:0> user2.deleted_devices
=> [#<DeletedDevice _id: 638340dd2efba3084a1b36af, created_at: 2022-11-27 10:50:05.692256 UTC, updated_at: 2022-11-27 10:50:12.892345 UTC, user_id: BSON::ObjectId('638340dd2efba3084a1b36ae')>]

device now belongs to user2:

irb(main):009:0> device.user == user2
=> true
irb(main):010:0> device.user == user1
=> false

user1's association is now empty, and destroying it doesn't destroy device:

irb(main):011:0> user1.deleted_devices
=> []
irb(main):012:0> user1.destroy
=> true
irb(main):013:0> device.reload
=> #<DeletedDevice _id: 638340dd2efba3084a1b36af, created_at: 2022-11-27 10:50:05.692 UTC, updated_at: 2022-11-27 10:50:12.892 UTC, user_id: BSON::ObjectId('638340dd2efba3084a1b36ae')>

Relevant versions

Gemfile.lock
    mongoid (8.0.2)
    rails (7.0.4)

$ brew info mongodb-community
==> mongodb/brew/mongodb-community: stable 6.0.1
pmv
  • 186
  • 1
  • 4