So I expect there to be an update method...
There isn't. You have to perform those steps manually.
This is how I would do this:
public function updateBillingAddress($array)
{
$billingAddress = $this->billingAddress->fill($array)->save();
$this->billingAddress()->associate($billingAddress);
$this->save();
return $billingAddress;
}
As you use ->withDefault() in your relationship definition you already have a new instance there.
If you want to avoid the implicit select query when you know beforehand there is no billing address, you would need to do something very similar to your first code sample.
public function updateBillingAddress($array)
{
$billingAddress = is_null($this->billing_address_id)
? new Address()
: $this->billingAddress;
$billingAddress->fill($array)->save();
$this->billingAddress()->associate($billingAddress);
$this->save();
return $billingAddress;
}