ruby-on-railsactiverecordruby-on-rails-6has-one

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?


Solution

  • 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