Sean Magyar
Sean Magyar

Reputation: 2380

Rails preferred way of setting foreign_key to nil on child

I have a has_one relationship with Device and Car.

What's the preferred way with ActiveRecord for removing the child from the parent (setting the device_id nil on the car but NOT deleting the car itself)?

When the device.car = nil line runs it gets committed immediately to the database. I want it to be committed only on save and return some useful error if it doesn't get saved.

I know I could also try to lookup the car, set the dongle_id to nil and save that, but this action is rather about the device than the car.

mutation:

def disconnect_car_and_device(id:)
  device = Device.find(id)

  authorize(current_user, device)

  device.car = nil

  if device.save
    { device: device, errors: [] }
  else
    { device: nil, errors: build_errors(device.errors) }
  end
end

models:

class Device < ApplicationRecord
  has_one :car
end

class Car < ApplicationRecord
  belongs_to :device
end

Upvotes: 0

Views: 76

Answers (2)

Yuri Afanasyev
Yuri Afanasyev

Reputation: 11

def disconnect_car_and_device(id:)
  device = Device.find(id)

  authorize(current_user, device)

  device.transaction do
    device.car = nil

    if device.save
      { device: device, errors: [] }
    else
      raise ActiveRecord::Rollback
      { device: nil, errors: build_errors(device.errors) }
    end
  end
end

Upvotes: 1

lbhise
lbhise

Reputation: 136

After trying different ways I found below code to work as expected :

def disconnect_car_and_device(id:)
  device = Device.find(id)

  authorize(current_user, device)
  car = device.car

  if device.save && car.update(device: nil)
    { device: device, errors: [] }
  else
    { device: nil, errors: build_errors(device.errors) }
  end
end

Upvotes: 1

Related Questions