stevec
stevec

Reputation: 52937

has_one association with optional: true?

In a simple booking app:

The Appointment record cannot be created first, since the passenger may not pay, in which case the TempAppointment stays as-in, and an associated Appointment record never gets created.

My natural thinking is that a TempAppointment has_one Appointment (which works), but when I add optional: true, I see errors:

class TempAppointment < ApplicationRecord
  has_one :appointment, optional: true 
end

try to create a new TempAppointment

ta = TempAppointment.new(cruise_id: 1, passenger_id: 1, start_time: start_time, end_time: start_time + 3600)
ArgumentError: Unknown key: :optional. Valid keys are: :class_name, :anonymous_class, :foreign_key,
 :validate, :autosave, :foreign_type, :dependent, :primary_key, :inverse_of, :required, :as, :touch

Why can't has_one work with optional: true?

Upvotes: 3

Views: 10148

Answers (3)

lucyjosef
lucyjosef

Reputation: 762

has_one is optional: true by default (even if it isn't really an option of this method, I mean has_one never means it is require)

So if you set the optional: true to the other model, be careful, this means that this other model doesn't need to be in a relationship with the first one. It's a one way dependence.

# your model_a doesn't need any model_b to exist
class ModelA < ApplicationRecord
  belongs_to :model_b, optional: true
  
  [...]
end

# same for model_b, it can exist without model_a
class ModelB < ApplicationRecord
  has_one :model_a
  
  [...]
end

But if you do

# your model_a has to belong to a model_b, otherwise it will fail
class ModelA < ApplicationRecord
  belongs_to :model_b
  
  [...]
end

# your model_b can still exist without model_a
class ModelB < ApplicationRecord
  has_one :model_a
  
  [...]
end

Upvotes: 8

Corey Sheesley
Corey Sheesley

Reputation: 46

On the Model where the has_one relationship is defined, I think you might be able to use required: false. So in the end, it would look something like this:

class Appointment < ApplicationRecord
  has_one :temp_appointment, required: false
end
class TempAppointment < ApplicationRecord
  belongs_to :appointment, optional: true 
end

https://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one

Upvotes: 3

stevec
stevec

Reputation: 52937

I switched the model associations around and it worked.

AFAIK, it makes no difference anywhere in the app.

Some helpful hints here

Here's what worked:

class Appointment < ApplicationRecord
  has_one :temp_appointment 
end
class TempAppointment < ApplicationRecord
  belongs_to :appointment, optional: true 
end

Upvotes: 3

Related Questions